From dc08d0475dff70d67cc371627a01f7dfde2bf479 Mon Sep 17 00:00:00 2001 From: Tibor Simko Date: Wed, 9 Sep 2015 16:14:28 +0200 Subject: [PATCH 01/12] installation: MySQL strict mode warning * Amends documentation to warn users about not using MySQL strict mode. (closes #905) Signed-off-by: Tibor Simko --- INSTALL | 3 +++ 1 file changed, 3 insertions(+) diff --git a/INSTALL b/INSTALL index 8e1342c79d..adaa8650f5 100644 --- a/INSTALL +++ b/INSTALL @@ -78,6 +78,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) Apache 2 server, with support for loading DSO modules, and From bbf3a3617448a824a1b3af93f72cce3f815a2a30 Mon Sep 17 00:00:00 2001 From: Archit Sharma Date: Sun, 9 Mar 2014 04:21:31 +0530 Subject: [PATCH 02/12] WebAccess: fix documentation grammar mistake Reviewed-by: Tibor Simko --- modules/webaccess/doc/hacking/webaccess-api.webdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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

From 2eb74cc7aa7bd35a76bf991943264aee08fc1c05 Mon Sep 17 00:00:00 2001
From: Sebastian Witowski 
Date: Mon, 23 Feb 2015 15:40:38 +0100
Subject: [PATCH 03/12] BibFormat: bibreformat missing cache fix

* FIX Changes when the missing caches are generated during bibreformat
  run. The missing cache is no longer generated for records if the
  bibreformat is run with -i, --collection, --field or --pattern
  option.

Signed-off-by: Sebastian Witowski 
Reviewed-by: Samuele Kaplun 
---
 modules/bibformat/lib/bibreformat.py | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

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)

From dde5aee99ab257447b54c4244a72726063f7620b Mon Sep 17 00:00:00 2001
From: Sebastian Witowski 
Date: Thu, 19 Feb 2015 14:37:29 +0100
Subject: [PATCH 04/12] WebSubmit: fix for Stamp_Uploaded_Files

* BETTER Allows the stamping function to accept both files and
  directories.

Signed-off-by: Sebastian Witowski 
---
 modules/websubmit/lib/functions/Stamp_Uploaded_Files.py | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

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:

From fa009b4397c2749dd9cec1c0b877d4d9524b7b73 Mon Sep 17 00:00:00 2001
From: Sebastian Witowski 
Date: Fri, 25 Oct 2013 11:32:09 +0200
Subject: [PATCH 05/12] BibDocFile: add download all files in BibRecDoc

* NEW Adds a new functionality that permits to obtain tarball of all
  the files associated with a record. For example,
  `/record/123/files/allfiles` includes all the original files in the
  tarball, `/record/123/files/allfiles-small` includes only icons of 180
  pixels, etc. The behaviour is governed by internal configuration
  variable `CFG_BIBDOCFILE_STREAM_ARCHIVE_FORMATS`.  (closes #1673)

Signed-off-by: Sebastian Witowski 
---
 modules/bibdocfile/lib/bibdocfile.py          | 65 +++++++++++++++++--
 modules/bibdocfile/lib/bibdocfile_config.py   |  9 +++
 .../bibdocfile/lib/bibdocfile_webinterface.py |  6 ++
 3 files changed, 74 insertions(+), 6 deletions(-)

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)
 

From 88a5bcb38c4c5cbf5e71af0cd3ed8380cebcbe91 Mon Sep 17 00:00:00 2001
From: Alessio Deiana 
Date: Mon, 12 Aug 2013 11:54:25 +0200
Subject: [PATCH 06/12] WebSearch: blacklist formats from search

* NEW Introduces a new internal configuration variable
  CFG_WEBSEARCH_BLACKLISTED_FORMATS that lists all the Invenio internal
  formats that should not be exposed via perform_request_search.
  (closes #1712)

Reviewed-by: Samuele Kaplun 
Signed-off-by: Alessio Deiana 
---
 modules/websearch/lib/search_engine.py        | 13 ++++++++++---
 modules/websearch/lib/search_engine_config.py |  5 +++++
 2 files changed, 15 insertions(+), 3 deletions(-)

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."""

From c6210046cb02e102dc0391e0063ad9a29382dfb3 Mon Sep 17 00:00:00 2001
From: Tibor Simko 
Date: Thu, 8 Oct 2015 10:20:06 +0200
Subject: [PATCH 07/12] WebSearch: fix async getter tests

* FIX Fixes asynchronous external collection getter tests following the
  update of the Invenio project web site.

Signed-off-by: Tibor Simko 
---
 .../lib/websearch_external_collections_getter_tests.py          | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/modules/websearch/lib/websearch_external_collections_getter_tests.py b/modules/websearch/lib/websearch_external_collections_getter_tests.py
index dc601c3293..933201bd5b 100644
--- a/modules/websearch/lib/websearch_external_collections_getter_tests.py
+++ b/modules/websearch/lib/websearch_external_collections_getter_tests.py
@@ -39,7 +39,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/'} ]
 

From 1ab268981c1e5e4700634cd86886c709700af297 Mon Sep 17 00:00:00 2001
From: Jochen Klein 
Date: Fri, 15 Jan 2016 14:29:32 +0100
Subject: [PATCH 08/12] BibFormat: format elements modifications

* Adds function parameter to add the title to the return value for
  all modified elements (optional).

* Adds INSPIRE-HEP-, CERN Phonebook-, and CERN profile page links
  to the profile links element (`bfe_authority_links`).

* Adds tooltip to show depended records for control numbers, instead of
  dislaying it after the control number (`bfe_authority_control_no`).

* Reimplementation of the element showing the publications.
  Changes the unordered list to an ordered (numerical) list for
  the publications and adds a new implementation for querying record ids
  for given control numbers (`bfe_authority_publications`).

Signed-off-by: Jochen Klein 
---
 .../lib/elements/bfe_authority_control_no.py  |  32 ++--
 .../lib/elements/bfe_authority_links.py       | 116 +++++++++++--
 .../elements/bfe_authority_publications.py    | 153 +++++++++---------
 3 files changed, 201 insertions(+), 100 deletions(-)

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_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): From bbc8bbc52120589481e8c27a4272ad230a32c96d Mon Sep 17 00:00:00 2001 From: Jochen Klein Date: Fri, 15 Jan 2016 14:42:40 +0100 Subject: [PATCH 09/12] BibFormat: new elements for author information * Adds bibformat element which returns contact information including an icon (optional). This includes email address, phone, mobile, and fax number. Allows requesting all information or a single one. * Adds bibformat element which returns work description including an icon (optional). Description contains "Home Institute (short) - Department/Group". Signed-off-by: Jochen Klein --- .../lib/elements/bfe_authority_contact.py | 114 ++++++++++++++++++ .../lib/elements/bfe_authority_description.py | 49 ++++++++ 2 files changed, 163 insertions(+) create mode 100644 modules/bibformat/lib/elements/bfe_authority_contact.py create mode 100644 modules/bibformat/lib/elements/bfe_authority_description.py 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..8bcf413d8f --- /dev/null +++ b/modules/bibformat/lib/elements/bfe_authority_contact.py @@ -0,0 +1,114 @@ +# -*- 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"): + """Return formatted email address.""" + if email_href.lower() == "yes": + email = "{0}".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"): + """Return formatted 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"): + """Return formatted mobile phone 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"): + """Return formatted 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", 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 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)) + if phone_number: + result += tbl_row.format( + _("Phone number"), format_phone_number(phone_number[0])) + 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_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 From 78d7ef22125d64422cd27b2e8ac20e944572e0d4 Mon Sep 17 00:00:00 2001 From: Jochen Klein Date: Fri, 15 Jan 2016 16:28:19 +0100 Subject: [PATCH 10/12] BibFormat: fix pre- and suffix for element include * Adds pre- and suffix to the bibformat elements include since HTML tags were removed from the return value of the elements itself. Signed-off-by: Jochen Klein --- .../etc/format_templates/Authority_HTML_detailed.bft | 6 +++--- .../etc/format_templates/Institute_HTML_detailed.bft | 6 +++--- .../etc/format_templates/Subject_HTML_detailed.bft | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) 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/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 @@ - - - + + + From ddb8688eac722e742a4b925f65a41378b85956ed Mon Sep 17 00:00:00 2001 From: Jochen Klein Date: Fri, 15 Jan 2016 16:34:22 +0100 Subject: [PATCH 11/12] BibFormat: HB/HD people template improvement * Improves the bibformat HTML templates HB and HD for people. Signed-off-by: Jochen Klein --- .../format_templates/People_HTML_brief.bft | 24 +++- .../format_templates/People_HTML_detailed.bft | 131 ++++++++++++++++-- 2 files changed, 146 insertions(+), 9 deletions(-) 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..072c6402bd 100644 --- a/modules/bibformat/etc/format_templates/People_HTML_detailed.bft +++ b/modules/bibformat/etc/format_templates/People_HTML_detailed.bft @@ -1,14 +1,129 @@ Authority HTML detailed Detailed Authority HTML format. -

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

Personal Information

+
+
+

Workspace

+ + + + + + + +
+
+
+

Contact

+ +
+
+

Profiles

+ +
+ +

Publications

+ From 57e3be8caf04ee1bf0e89488d21b239496a7af4a Mon Sep 17 00:00:00 2001 From: Jochen Klein Date: Mon, 25 Jan 2016 17:45:05 +0100 Subject: [PATCH 12/12] BibFormat: vCard support for people collection * Adds vCard support for detailed profile pages for the people collection and contains full name, affiliation, email, phone, mobile, and fax number. Uses microformats hCard 1.0. Signed-off-by: Jochen Klein --- .../format_templates/People_HTML_detailed.bft | 7 ++- .../lib/elements/bfe_authority_contact.py | 44 +++++++++++++++---- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/modules/bibformat/etc/format_templates/People_HTML_detailed.bft b/modules/bibformat/etc/format_templates/People_HTML_detailed.bft index 072c6402bd..ecf191c2d1 100644 --- a/modules/bibformat/etc/format_templates/People_HTML_detailed.bft +++ b/modules/bibformat/etc/format_templates/People_HTML_detailed.bft @@ -77,9 +77,10 @@ table tr td { } +
- - + +

Personal Information

@@ -112,6 +113,7 @@ table tr td {
@@ -121,6 +123,7 @@ table tr td { default="No profiles."/>
+

Publications

" + "" + "{0}" + "".format(phone_number)) if icon.lower() == "yes": icon_class = "fa fa-phone" phone_number = " {1}".format( @@ -41,8 +53,14 @@ def format_phone_number(phone_number, icon="no"): return phone_number -def format_mobile_number(mobile_number, icon="no"): +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( @@ -50,19 +68,27 @@ def format_mobile_number(mobile_number, icon="no"): return mobile_number -def format_fax_number(fax_number, icon="no"): +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", email_href="yes", icon="no"): +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' """ @@ -79,10 +105,12 @@ def format_element(bfo, contact_type="all", email_href="yes", icon="no"): tbl_row = "{0}{1}" if email: result += tbl_row.format( - _("Email address"), format_email(email[0].lower(), email_href)) + _("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])) + _("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]))