source: main/waeup.sirp/trunk/src/waeup/sirp/university/catalog.py @ 6875

Last change on this file since 6875 was 6839, checked in by Henrik Bettermann, 13 years ago

Use common and coherent naming convention for all event handlers.

File size: 5.1 KB
Line 
1"""Catalog and searching components for academics stuff.
2"""
3import grok
4from hurry.query import Eq, Text
5from hurry.query.query import Query
6from zope.catalog.interfaces import ICatalog
7from zope.component import getUtility
8from zope.component.interfaces import ComponentLookupError
9from zope.index.text.parsetree import ParseError
10from zope.intid import IIntIds
11#from waeup.sirp.catalog import QueryResultItem
12from waeup.sirp.interfaces import IUniversity, IQueryResultItem
13from waeup.sirp.university.interfaces import (
14    ICourse, ICertificateCourse, IDepartment,
15    ICertificate,
16    )
17
18class CourseIndexes(grok.Indexes):
19    """This catalog is needed for building sources.
20    """
21    grok.site(IUniversity)
22    grok.name('courses_catalog')
23    grok.context(ICourse)
24
25    code = grok.index.Field(attribute='code')
26    title = grok.index.Text(attribute='title')
27
28class CertificatesIndexes(grok.Indexes):
29    """This catalog is needed for building sources.
30    """
31    grok.site(IUniversity)
32    grok.name('certificates_catalog')
33    grok.context(ICertificate)
34
35    code = grok.index.Field(attribute='code')
36    application_category = grok.index.Field(attribute='application_category')
37
38class CertificateCoursesIndexes(grok.Indexes):
39    """This catalog is needed for automatic removal of certificate courses
40    and later for selection course tickets in the students section.
41    """
42    grok.site(IUniversity)
43    grok.name('certcourses_catalog')
44    grok.context(ICertificateCourse)
45
46    course_code = grok.index.Field(attribute='getCourseCode')
47    level = grok.index.Field(attribute='level')
48
49@grok.subscribe(ICourse, grok.IObjectAddedEvent)
50def handle_course_added(obj, event):
51    """Index an added course with the local catalog.
52
53    Courses are not indexed automatically, as they are not a
54    dictionary subitem of the accompanied site object
55    (`IUniversity`). I.e. one cannot get them by asking for
56    ``app['FACCODE']['DEPTCODE']['COURSECODE']`` but one has to ask for
57    ``app.faculties['FACCODE']['DEPTCODE'].courses['COURSECODE']``.
58
59    Once, a course is indexed we can leave the further handling to
60    the default component architechture. At least removals will
61    be handled correctly then (and the course unindexed).
62    """
63    try:
64        cat = getUtility(ICatalog, name='courses_catalog')
65    except ComponentLookupError:
66        # catalog not available. This might happen during tests.
67        return
68    intids = getUtility(IIntIds)
69    index = cat['code']
70    index.index_doc(intids.getId(obj), obj)
71
72@grok.subscribe(ICourse, grok.IObjectAddedEvent)
73def handle_certificate_added(obj, event):
74    """Index an added certificate with the local catalog.
75
76    See handleCourseAdd.
77    """
78    try:
79      cat = getUtility(ICatalog, name='certificates_catalog')
80    except ComponentLookupError:
81      # catalog not available. This might happen during tests.
82      return
83    intids = getUtility(IIntIds)
84    index = cat['code']
85    index.index_doc(intids.getId(obj), obj)
86
87@grok.subscribe(ICertificateCourse, grok.IObjectAddedEvent)
88def handlecertificatecourse_added(obj, event):
89    """Index an added certificatecourse with the local catalog.
90
91    See handleCourseAdd.
92    """
93    try:
94      cat = getUtility(ICatalog, name='certcourses_catalog')
95    except ComponentLookupError:
96      # catalog not available. This might happen during tests.
97      return
98    intids = getUtility(IIntIds)
99    index = cat['course_code']
100    index.index_doc(intids.getId(obj), obj)
101
102@grok.subscribe(IDepartment, grok.IObjectRemovedEvent)
103def handle_department_removed(obj, event):
104    """Clear courses and certificates when a department is killed.
105    """
106    obj.courses.clear()
107    obj.certificates.clear()
108    return
109
110class CoursesQueryResultItem(object):
111    grok.implements(IQueryResultItem)
112
113    def __init__(self, context, view):
114        self.context = context
115        self.url = view.url(context)
116        self.title = context.title
117        self.code = context.code
118        self.type = 'Course'
119
120class CertificateCoursesQueryResultItem(object):
121    grok.implements(IQueryResultItem)
122
123    def __init__(self, context, view):
124        self.context = context
125        self.url = view.url(context)
126        self.title = context.course.title
127        self.code = context.getCourseCode
128        self.type = 'Course Referrer'
129
130def search(query=None, view=None):
131    if not query:
132        view.flash('Empty search string.')
133        return
134
135    hitlist = []
136    try:
137        results = Query().searchResults(
138            Eq(('courses_catalog', 'code'), query))
139        for result in results:
140            hitlist.append(CoursesQueryResultItem(result, view=view))
141        results = Query().searchResults(
142            Text(('courses_catalog', 'title'), query))
143        for result in results:
144            hitlist.append(CoursesQueryResultItem(result, view=view))
145
146        results = Query().searchResults(
147            Eq(('certcourses_catalog', 'course_code'), query))
148        for result in results:
149            hitlist.append(CertificateCoursesQueryResultItem(result, view=view))
150    except ParseError:
151        view.flash('Search string not allowed.')
152        return
153    return hitlist
Note: See TracBrowser for help on using the repository browser.