Passed
Push — 2.x ( 14146c...e51f61 )
by Jordi
05:29
created

senaite.core.catalog.utils   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 107
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 16
eloc 66
dl 0
loc 107
rs 10
c 0
b 0
f 0

4 Functions

Rating   Name   Duplication   Size   Complexity  
A sortable_sortkey_title() 0 12 3
B get_searchable_text_tokens() 0 54 7
A sortable_title() 0 7 2
A get_metadata_for() 0 16 4
1
# -*- coding: utf-8 -*-
2
3
from bika.lims import api
4
from bika.lims import logger
5
from bika.lims.interfaces import IListingSearchableTextProvider
6
from Products.CMFPlone.CatalogTool import \
7
    sortable_title as plone_sortable_title
8
from Products.CMFPlone.utils import safe_callable
9
from zope.component import getAdapters
10
11
12
def get_searchable_text_tokens(instance, catalog_name,
13
                               exclude_field_names=None,
14
                               include_field_names=None):
15
    """Retrieves all the values of metadata columns in the catalog for
16
    wildcard searches
17
18
    :param instance: the object to retrieve metadata/values from
19
    :param catalog_name: the catalog to retrieve metadata from
20
    :param exclude_field_names: field names to exclude from the metadata
21
    :param include_field_names: field names to include, even if no metadata
22
    :returns: list of unified searchable text tokes
23
    """
24
    entries = set()
25
26
    # Fields to include/exclude
27
    include = include_field_names or []
28
    exclude = exclude_field_names or []
29
30
    # Get the metadata fields from this instance and catalog
31
    catalog = api.get_tool(catalog_name)
32
    metadata = get_metadata_for(instance, catalog)
33
    for key, brain_value in metadata.items():
34
        if key in exclude:
35
            continue
36
        elif key in include:
37
            # A metadata field already
38
            include.remove(key)
39
40
        instance_value = api.safe_getattr(instance, key, None)
41
        parsed = api.to_searchable_text_metadata(brain_value or instance_value)
42
        entries.add(parsed)
43
44
    # Include values from additional fields
45
    for field_name in include:
46
        field_value = api.safe_getattr(instance, field_name, None)
47
        field_value = api.to_searchable_text_metadata(field_value)
48
        entries.add(field_value)
49
50
    # Extend metadata entries with pluggable text providers
51
    for name, adapter in getAdapters((instance, catalog),
52
                                     IListingSearchableTextProvider):
53
        value = adapter()
54
        if isinstance(value, (list, tuple)):
55
            values = map(api.to_searchable_text_metadata, value)
56
            entries.update(values)
57
        else:
58
            value = api.to_searchable_text_metadata(value)
59
            entries.add(value)
60
61
    # Remove empties
62
    entries = filter(None, entries)
63
64
    # return a list of searchable text tokes
65
    return list(entries)
66
67
68
def get_metadata_for(instance, catalog):
69
    """Returns the metadata for the given instance from the specified catalog
70
    """
71
    path = api.get_path(instance)
72
    try:
73
        return catalog.getMetadataForUID(path)
74
    except KeyError:
75
        logger.info("Generating catalog metadata for '{}' manually"
76
                    .format(path))
77
        metadata = {}
78
        for key in catalog.schema():
79
            attr = getattr(instance, key, None)
80
            if callable(attr):
81
                attr = attr()
82
            metadata[key] = attr
83
        return metadata
84
85
86
def sortable_title(instance):
87
    """Uses the default Plone sortable_text index lower-case
88
    """
89
    title = plone_sortable_title(instance)
90
    if safe_callable(title):
91
        title = title()
92
    return title.lower()
93
94
95
def sortable_sortkey_title(instance):
96
    """Returns a sortable title as a mxin of sortkey + lowercase sortable_title
97
    """
98
    title = sortable_title(instance)
99
    if safe_callable(title):
100
        title = title()
101
102
    sort_key = instance.getSortKey()
103
    if sort_key is None:
104
        sort_key = 999999
105
106
    return "{:010.3f}{}".format(sort_key, title)
107