Package: horae.search
IntroductionThehorae.searchprovides searching functionality for the Horae
resource planning system by implementing a ajax driven full text search
and a pluggable advanced search form. Additionally it implements a
restricted specialQueryimplementation based on the one provided
byhurry.querywhich only
returns results the user is allowed to see.UsageThere are several ways to extend and adjust the behaviour of the search
forms and results by registering special adapters. The following possibilities
are available for any views sub-classing fromhorae.search.search.SearchMixin.Extending the advanced search formThe advanced search form may be extended by registering a named multi adapter
implementinghorae.search.interfaces.IAdvancedSearchFieldProviderand adapting thecontextandrequest. If for example one would
like to add a newTextLinefield searching in a custom catalog the
implementation would look something like this:import grok

from zope import interface
from zope import schema
from zope.publisher.interfaces.browser import IBrowserRequest

from hurry import query

from horae.search import interfaces

class SampleAdvancedSearchFieldProvider(grok.MultiAdapter):
    grok.adapts(interface.Interface, IBrowserRequest)
    grok.implements(interfaces.IAdvancedSearchFieldProvider)
    grok.name('sampleadvancedfieldprovider')

    def __init__(self, context, request):
        self.context = context
        self.request = request

    def fields(self):
        """ Returns a list of fields to be added to the form
        """
        return [
            schema.TextLine(
                __name__ = 'sample_text_line',
                title = u'Sample text line'
            )
        ]

    def query(self, **data):
        """ Returns a list of queries
        """
        queries = []
        if 'sample_text_line' in data:
            queries.append(query.Text(('samplecatalog', 'text'),
                                      data['sample_text_line']))
        return queriesAdjusting default sortingBy default the search results are sorted by a special integer index in the catalog.
This integer may be adjusted by registering a named adapter implementinghorae.search.interfaces.ISortingProviderand adapting the object the sorting
should be changed for. If for example one would like to move every ticket having
a special property set to the bottom of the search results the implementation
would look like this:from horae.ticketing.interfaces import ITicket

class SampleSortingProvider(grok.Adapter):
    grok.context(ITicket)
    grok.implements(interfaces.ISortingProvider)
    grok.name('samplesortingprovider')

    def add(self):
        """ Returns an integer to be added to the sorting
        """
        return 0

    def adjust(self, sorting):
        """ Adjusts the sorting after all providers sorting
            where added and returns the adjusted sorting
        """
        if (self.context.get_property('my_special_property', None) is not None):
            return 0
        return sortingChanging default sortingAs mentioned above the default sorting of the search results is a special integer index
in the catalog. This may be changed by registering an adapter implementinghorae.search.interfaces.IDefaultSortingProviderand adapting either the
search view or the search view and the desired context. An example implementation
changing the default sorting of the advanced search results would look like this:from horae.search import search

class SampleDefaultSortingProvider(grok.Adapter):
    grok.context(search.AdvancedSearch)
    grok.implements(interfaces.IDefaultSortingProvider)

    def sort_field(self):
        """ The index used to sort
        """
        return ('samplecatalog', 'sorting')

    def reverse(self):
        """ Whether to reverse the sort order
        """
        return FalseAdding columnsAdding new columns to the results table is possible by registering a named adapter
implementinghorae.search.interfaces.IColumnProvideradapting the desiredcontext.
The following is an example implementation found inhorae.search.searchproviding
a column showing whether an object has been completed or not:class CompleteColumnProvider(grok.Adapter):
    """ Column provider adding the complete column
    """
    grok.implements(interfaces.IColumnProvider)
    grok.context(interface.Interface)
    grok.name('horae.search.column.complete')

    name = 'complete'
    title = _(u'Completed')
    sortable = None
    insert_after = '*'

    def __init__(self, context):
        self.context = context

    def filterable(self):
        """ Returns a vocabulary for filtering the column or
            None if no filtering is available
        """
        return vocabulary.SimpleVocabulary([
            vocabulary.SimpleTerm(0, 'no', _p(u'No')),
            vocabulary.SimpleTerm(1, 'yes', _p(u'Yes'))
        ])

    def factory(self, object, request):
        """ Returns the value to be displayed for the given object
        """
        return (IComplete(object, lambda: False)() and _p(u'Yes') or _p(u'No'))

    def cache_key(self, key, *args, **kwargs):
        """ Modifies the cache key if needed and returns it
        """
        return key + parents_modification_cache_key(self.context)Adding row CSS classLast but not least one may add custom CSS classes to the rows by registering
a named adapter implementinghorae.search.interfaces.IRowClassProvideradapting the desiredcontext. An example implementation adding a CSS classspecialif a ticket has a special property set would look like this:class SampleRowClassProvider(grok.Adapter):
    grok.context(ITicket)
    grok.implements(interfaces.IRowClassProvider)

    def classes(self):
        """ Returns a list of CSS classes to be set on the row
        """
        if (self.context.get_property('my_special_property', None) is not None):
            return ['special']
        return []DependenciesHoraehorae.authhorae.autocompletehorae.cachehorae.corehorae.layouthorae.lifecyclehorae.propertieshorae.ticketingThird partygrokzc.cataloghurry.queryChangelog1.0a1 (2012-01-16)Initial release