2
# SchoolTool - common information systems platform for school administration
3
# Copyright (c) 2005 Shuttleworth Foundation
5
# This program is free software; you can redistribute it and/or modify
6
# it under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 2 of the License, or
8
# (at your option) any later version.
10
# This program is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
15
# You should have received a copy of the GNU General Public License
16
# along with this program; if not, write to the Free Software
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
from zope.component import queryUtility
21
from zope.location import location
22
from zope.interface import implements
23
from zope.publisher.interfaces import IPublishTraverse, NotFound
24
from zope.security.checker import canAccess
25
from zope.security.interfaces import Unauthorized
26
from zope.security.proxy import removeSecurityProxy
28
from schooltool.app.interfaces import ISchoolToolApplication
29
from schooltool.intervention import interfaces
30
from schooltool.intervention.intervention import getInterventionStudent
31
from schooltool.person.interfaces import IPerson
32
from schooltool.term.interfaces import IDateManager
33
from schooltool.traverser.traverser import NameTraverserPlugin
36
class InterventionTabProxy(object):
37
"""Proxy used as context of the Intervention tab views."""
38
implements(interfaces.IInterventionTabProxy)
40
def __init__(self, user):
44
class InterventionTabTraverserPlugin(NameTraverserPlugin):
45
"""Traverses from a user's BasicPerson object to the Intervention tab
46
proxy which in turn will serve as context to the Intervention tab views.
48
i.e. if you go to localhost/persons/someuser/intervention_tab this traverser
49
will get called instead of standard traverser. It returns an
50
InterventionTabProxy for the user.
53
traversalName = "intervention_tab"
54
def _traverse(self, request, name):
55
person = IPerson(request.principal, None)
56
if person is None or person.username != self.context.username:
57
raise NotFound(self.context, name, request)
58
proxyInterventionTab = InterventionTabProxy(self.context)
59
return location.LocationProxy(proxyInterventionTab, self.context,
63
class StudentSchoolYearsProxy(object):
64
"""Proxy used for traversing to a student message or goal."""
66
def __init__(self, student):
67
self.student = student
70
class StudentSchoolYearsTraverserPlugin(NameTraverserPlugin):
71
"""Represents the first step in traversing from a student to a goal or
74
i.e. if you go to localhost/persons/somestudent/schoolyears this traverser
75
will get called instead of standard traverser. It returns the an
76
StudentSchoolYearsProxy for the student.
79
traversalName = "schoolyears"
80
def _traverse(self, request, name):
81
proxySchoolYears = StudentSchoolYearsProxy(self.context)
82
return location.LocationProxy(proxySchoolYears, self.context,
86
class StudentSchoolYearProxy(object):
87
"""Proxy used for traversing to a student message or goal."""
88
implements(interfaces.IStudentSchoolYearProxy)
90
def __init__(self, year):
91
self.year = removeSecurityProxy(year)
94
class StudentSchoolYearTraverser(object):
95
"""Allows traversal to a student's schoolyear proxy.
97
i.e. if you go to localhost/persons/somestudent/schoolyears/someyear this
98
traverser will get called instead of standard traverser. It also wraps the
99
message in a location proxy so the url looks like what is above.
101
The whole reason for having this traversal adaptation is to allow
102
persons responsible to see messages or goals for students that they
103
are not teaching, advising or administrating.
105
implements(IPublishTraverse)
107
def __init__(self, context, request):
108
self.context = context
109
self.request = request
111
def publishTraverse(self, request, name):
112
app = ISchoolToolApplication(None)
113
interventionRoot = app[u'schooltool.interventions']
114
if name not in interventionRoot:
115
raise NotFound(self.context, name, request)
116
proxySchoolYear = StudentSchoolYearProxy(interventionRoot[name])
117
return location.LocationProxy(proxySchoolYear, self.context,
121
class StudentMessagesGoalsProxy(object):
122
"""Proxy used for traversing to a student message or goal."""
124
def __init__(self, type):
128
class StudentMessagesGoalsTraverser(object):
129
"""Allows traversal to a student's schoolyear proxy.
131
i.e. go to localhost/persons/somestudent/schoolyears/someyear/messages or
132
goals and this traverser will get called instead of standard traverser.
133
It also wraps the message in a location proxy so the url looks like what
136
The whole reason for having this traversal adaptation is to allow
137
persons responsible to see messages or goals for students that they
138
are not teaching, advising or administrating.
140
implements(IPublishTraverse)
142
def __init__(self, context, request):
143
self.context = context
144
self.request = request
146
def publishTraverse(self, request, name):
147
proxyMessagesGoals = StudentMessagesGoalsProxy(name)
148
return location.LocationProxy(proxyMessagesGoals, self.context,
152
class StudentMessageGoalTraverser(object):
153
"""Allows traversal to a student's schoolyear proxy.
155
i.e. localhost/persons/somestudent/schoolyears/someyear/goals/somegoal or
156
message and this traverser will get called instead of standard traverser.
157
It also wraps the message in a location proxy so the url looks like what
160
The whole reason for having this traversal adaptation is to allow
161
persons responsible to see messages or goals for students that they
162
are not teaching, advising or administrating.
164
implements(IPublishTraverse)
166
def __init__(self, context, request):
167
self.context = context
168
self.request = request
170
def publishTraverse(self, request, name):
171
context = removeSecurityProxy(self.context)
172
yearproxy = removeSecurityProxy(context.__parent__)
173
yearsproxy = removeSecurityProxy(yearproxy.__parent__)
174
student = removeSecurityProxy(yearsproxy.student)
175
interventionStudent = removeSecurityProxy(
176
yearproxy.year[student.username])
177
messagesGoals = interventionStudent[context.type]
178
if name not in messagesGoals:
179
raise NotFound(self.context, name, request)
180
messageGoal = messagesGoals[name]
181
if not canAccess(messageGoal, 'created'):
183
return location.LocationProxy(messageGoal, self.context,
187
class InterventionStudentTraverserPlugin(NameTraverserPlugin):
188
"""Allows traversal to a student's intervention object.
190
i.e. if you go to localhost/persons/somestudent/intervention this traverser
191
will get called instead of standard traverser. It returns the student's
192
intervention object for the current school year.
195
traversalName = "intervention"
196
def _traverse(self, request, name):
197
if queryUtility(IDateManager).current_term is None:
199
interventionStudent = getInterventionStudent(self.context.__name__)
200
return interventionStudent
203
class SectionMessagesProxy(object):
204
"""Proxy used for traversing to a section's student messages."""
206
def __init__(self, section):
207
self.section = section
210
class SectionMessagesTraverserPlugin(NameTraverserPlugin):
211
"""Allows traversal from a section object to a SectionMessagesProxy
212
object, which in turn will be used to traverse to the messages
213
container for a given student.
215
i.e. if you go to localhost/sections/somesec/messages this traverser
216
will get called instead of standard traverser.
219
traversalName = "messages"
220
def _traverse(self, request, name):
221
proxyMessages = SectionMessagesProxy(self.context)
222
return location.LocationProxy(proxyMessages, self.context,
225
class SectionMessagesTraverser(object):
226
"""Allows traversal to a student's messages container from the
227
section messages proxy.
229
i.e. if you go to localhost/sections/somesec/messages/someone this
230
traverser will get called instead of standard traverser. It also wraps the
231
message in a location proxy so the url looks like what is above.
233
The whole reason for having this traversal adaptation is to allow
234
the message add view to know what section the message is for.
236
implements(IPublishTraverse)
238
def __init__(self, context, request):
239
self.context = context
240
self.request = request
242
def publishTraverse(self, request, name):
243
interventionStudent = getInterventionStudent(name)
244
messages = interventionStudent['messages']
245
messages = location.LocationProxy(messages, self.context, name)