source: main/waeup.kofa/trunk/src/waeup/kofa/university/catalog.py @ 9631

Last change on this file since 9631 was 9631, checked in by Henrik Bettermann, 12 years ago

Display faculty and department in search result tables.

  • Property svn:keywords set to Id
File size: 7.2 KB
Line 
1## $Id: catalog.py 9631 2012-11-14 09:09:14Z henrik $
2##
3## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18"""Catalog and searching components for academics stuff.
19"""
20import grok
21from hurry.query import Eq, Text
22from hurry.query.query import Query
23from zope.catalog.interfaces import ICatalog
24from zope.component import getUtility
25from zope.component.interfaces import ComponentLookupError
26from zope.index.text.parsetree import ParseError
27from zope.intid import IIntIds
28#from waeup.kofa.catalog import QueryResultItem
29from waeup.kofa.interfaces import IUniversity, IQueryResultItem
30from waeup.kofa.university.interfaces import (
31    ICourse, ICertificateCourse, IDepartment,
32    ICertificate,
33    )
34
35class CourseIndexes(grok.Indexes):
36    """This catalog is needed for building sources.
37    """
38    grok.site(IUniversity)
39    grok.name('courses_catalog')
40    grok.context(ICourse)
41
42    code = grok.index.Field(attribute='code')
43    title = grok.index.Text(attribute='title')
44
45class CertificatesIndexes(grok.Indexes):
46    """This catalog is needed for building sources.
47    """
48    grok.site(IUniversity)
49    grok.name('certificates_catalog')
50    grok.context(ICertificate)
51
52    code = grok.index.Field(attribute='code')
53    application_category = grok.index.Field(attribute='application_category')
54    title = grok.index.Text(attribute='title')
55
56class CertificateCoursesIndexes(grok.Indexes):
57    """This catalog is needed for automatic removal of certificate courses
58    and later for selection of course tickets in the students section.
59    """
60    grok.site(IUniversity)
61    grok.name('certcourses_catalog')
62    grok.context(ICertificateCourse)
63
64    course_code = grok.index.Field(attribute='getCourseCode')
65    level = grok.index.Field(attribute='level')
66
67@grok.subscribe(ICourse, grok.IObjectAddedEvent)
68def handle_course_added(obj, event):
69    """Index an add course with the local catalog.
70
71    Courses are not indexed automatically, as they are not a
72    dictionary subitem of the accompanied site object
73    (`IUniversity`). I.e. one cannot get them by asking for
74    ``app['FACCODE']['DEPTCODE']['COURSECODE']`` but one has to ask for
75    ``app.faculties['FACCODE']['DEPTCODE'].courses['COURSECODE']``.
76
77    Once, a course is indexed we can leave the further handling to
78    the default component architechture. At least removals will
79    be handled correctly then (and the course unindexed).
80    """
81    try:
82        cat = getUtility(ICatalog, name='courses_catalog')
83    except ComponentLookupError:
84        # catalog not available. This might happen during tests.
85        return
86    intids = getUtility(IIntIds)
87    index = cat['code']
88    index.index_doc(intids.getId(obj), obj)
89
90@grok.subscribe(ICourse, grok.IObjectAddedEvent)
91def handle_certificate_added(obj, event):
92    """Index an added certificate with the local catalog.
93
94    See handleCourseAdd.
95    """
96    try:
97      cat = getUtility(ICatalog, name='certificates_catalog')
98    except ComponentLookupError:
99      # catalog not available. This might happen during tests.
100      return
101    intids = getUtility(IIntIds)
102    index = cat['code']
103    index.index_doc(intids.getId(obj), obj)
104
105@grok.subscribe(ICertificateCourse, grok.IObjectAddedEvent)
106def handlecertificatecourse_added(obj, event):
107    """Index an added certificatecourse with the local catalog.
108
109    See handleCourseAdd.
110    """
111    try:
112      cat = getUtility(ICatalog, name='certcourses_catalog')
113    except ComponentLookupError:
114      # catalog not available. This might happen during tests.
115      return
116    intids = getUtility(IIntIds)
117    index = cat['course_code']
118    index.index_doc(intids.getId(obj), obj)
119
120@grok.subscribe(IDepartment, grok.IObjectRemovedEvent)
121def handle_department_removed(obj, event):
122    """Clear courses and certificates when a department is killed.
123    """
124    # We cannot use the 'clear()' method of respective subcontainers
125    # (courses, certificates), because that would not trigger
126    # IObjectRemoved events.
127    for subobj_name in ['courses', 'certificates']:
128        key_list = list(getattr(obj, subobj_name, []).keys())
129        for key in key_list:
130            del getattr(obj, subobj_name)[key]
131    return
132
133class CoursesQueryResultItem(object):
134    grok.implements(IQueryResultItem)
135
136    def __init__(self, context, view):
137        self.context = context
138        self.url = view.url(context)
139        self.title = context.title
140        self.code = context.code
141        self.dep = context.__parent__.__parent__.code
142        self.fac = context.__parent__.__parent__.__parent__.code
143        self.type = 'Course'
144
145class CertificatesQueryResultItem(object):
146    grok.implements(IQueryResultItem)
147
148    def __init__(self, context, view):
149        self.context = context
150        self.url = view.url(context)
151        self.title = context.title
152        self.code = context.code
153        self.dep = context.__parent__.__parent__.code
154        self.fac = context.__parent__.__parent__.__parent__.code
155        self.type = 'Certificate'
156
157class CertificateCoursesQueryResultItem(object):
158    grok.implements(IQueryResultItem)
159
160    def __init__(self, context, view):
161        self.context = context
162        self.url = view.url(context)
163        self.title = context.course.title
164        self.code = context.getCourseCode
165        self.dep = context.__parent__.__parent__.__parent__.code
166        self.fac = context.__parent__.__parent__.__parent__.__parent__.code
167        self.type = 'Certificate Course'
168
169def search(query=None, view=None):
170    if not query:
171        view.flash('Empty search string.')
172        return
173
174    hitlist = []
175    try:
176        results = Query().searchResults(
177            Eq(('courses_catalog', 'code'), query))
178        for result in results:
179            hitlist.append(CoursesQueryResultItem(result, view=view))
180        results = Query().searchResults(
181            Text(('courses_catalog', 'title'), query))
182        for result in results:
183            hitlist.append(CoursesQueryResultItem(result, view=view))
184        results = Query().searchResults(
185            Eq(('certificates_catalog', 'code'), query))
186        for result in results:
187            hitlist.append(CertificatesQueryResultItem(result, view=view))
188        results = Query().searchResults(
189            Text(('certificates_catalog', 'title'), query))
190        for result in results:
191            hitlist.append(CertificatesQueryResultItem(result, view=view))
192        results = Query().searchResults(
193            Eq(('certcourses_catalog', 'course_code'), query))
194        for result in results:
195            hitlist.append(CertificateCoursesQueryResultItem(result, view=view))
196    except ParseError:
197        view.flash('Search string not allowed.')
198        return
199    return hitlist
Note: See TracBrowser for help on using the repository browser.