source: WAeUP_SRP/base/Widgets.py @ 3493

Last change on this file since 3493 was 3493, checked in by Henrik Bettermann, 16 years ago

resolve ticket #366 comment 05/06/08 14:33:55

  • Property svn:keywords set to Id
File size: 94.4 KB
Line 
1#-*- mode: python; mode: fold -*-
2# $Id: Widgets.py 3493 2008-05-07 08:39:45Z henrik $
3from cgi import escape
4from types import *
5import Globals
6from Globals import InitializeClass
7from ZPublisher.HTTPRequest import FileUpload
8from OFS.Image import cookId, File, Image
9##from Products.CPSSchemas.Widget import CPSWidgetType
10from Products.CMFCore.utils import getToolByName
11from Products.CPSSchemas.BasicWidgets import CPSBooleanWidget, CPSWidget, CPSStringWidget, CPSEmailWidget,CPSImageWidget
12from Products.CPSSchemas.BasicWidgets import CPSFileWidget, CPSPasswordWidget
13from Products.CPSSchemas.BasicWidgets import renderHtmlTag,CPSSelectWidget, CPSStringWidget
14from Products.CPSSchemas.ExtendedWidgets import CPSDateTimeWidget
15from Products.CPSSchemas.Vocabulary import Vocabulary
16from Products.CPSSchemas.Widget import widgetRegistry
17from Products.CPSUtil.file import PersistableFileUpload
18from Products.CPSUtil.id import generateFileName
19##from Products.CPSSchemas.WidgetTypesTool import WidgetTypeRegistry
20from DateTime.DateTime import DateTime
21from AccessControl import getSecurityManager
22from Products.WAeUP_SRP.Students import getStudentByRegNo
23from Products.WAeUP_SRP.Academics import makeCertificateCode
24from Products.WAeUP_SRP.WAeUPTool import getImagesDir
25#from Products.ExtFile.ExtFile import ExtFile
26import logging,os,re
27import random
28import operator
29p_home = Globals.package_home(globals())
30i_home = Globals.INSTANCE_HOME
31
32#from zLOG import LOG, DEBUG
33
34
35class WAeUPPasswordWidget(CPSPasswordWidget): ###(
36    """WAeUP Password Widget"""
37    meta_type = 'WAeUP Password Widget'
38
39    _properties = CPSStringWidget._properties + (
40        {'id': 'password_widget', 'type': 'string', 'mode': 'w',
41         'label': 'Password widget to compare with'},
42        {'id': 'check_lower', 'type': 'boolean', 'mode': 'w',
43         'label': 'Checking at least one lower case [a-z]'},
44        {'id': 'check_upper', 'type': 'boolean', 'mode': 'w',
45         'label': 'Checking at least one upper case [A-Z]'},
46        {'id': 'check_digit', 'type': 'boolean', 'mode': 'w',
47         'label': 'Checking at least one digit [0-9]'},
48        {'id': 'check_extra', 'type': 'boolean', 'mode': 'w',
49         'label': 'Checking at least one extra char other than [a-zA-Z0-9]'},
50        {'id': 'check_words', 'type': 'string', 'mode': 'w',
51         'label': 'Checking for words'},
52        )
53
54    field_types = ('CPS Password Field',)
55    password_widget = ''
56    check_lower = 0
57    check_upper = 0
58    check_digit = 0
59    check_extra = 0
60    check_words = ''
61    display_width = 8
62    size_min = 5
63    size_max = 8
64
65    def validate(self, datastructure, **kw):
66        """Validate datastructure and update datamodel."""
67        widget_id = self.getWidgetId()
68        value = datastructure[widget_id]
69        err = 0
70        try:
71            v = str(value).strip()
72        except ValueError:
73            err = 'cpsschemas_err_string'
74        else:
75            if self.password_widget:
76                # here we only check that that our confirm match the pwd
77                pwidget_id = self.password_widget
78                pvalue = datastructure[pwidget_id]
79                datastructure[widget_id] = ''
80                datastructure[pwidget_id] = ''
81                pv = str(pvalue).strip()
82                if pv and v != pv:
83                    err = 'cpsschemas_err_password_mismatch'
84            else:
85                if not v:
86                    if self.is_required:
87                        datamodel = datastructure.getDataModel()
88                        if not datamodel[self.fields[0]]:
89                            err = 'cpsschemas_err_required'
90                else:
91                    # checking pw consistancy
92                    len_v = len(v)
93                    if not err and self.size_max and len_v > self.size_max:
94                        err = 'cpsschemas_err_string_too_long'
95                    if not err and self.size_min and len_v < self.size_min:
96                        err = 'cpsschemas_err_password_size_min'
97                    if not err and self.check_lower and not search(r'[a-z]', v):
98                        err = 'cpsschemas_err_password_lower'
99                    if not err and self.check_upper and not search(r'[A-Z]', v):
100                        err = 'cpsschemas_err_password_upper'
101                    if not err and self.check_digit and not search(r'[0-9]', v):
102                        err = 'cpsschemas_err_password_digit'
103                    if not err and self.check_extra and not search(r'[^a-zA-Z0-9]',
104                                                                   v):
105                        err = 'cpsschemas_err_password_extra'
106                    if not err and v in self.check_words:
107                        err = 'Your password is unsecure, please choose another password!'
108
109        if err:
110            datastructure[widget_id] = ''
111            datastructure.setError(widget_id, err)
112        elif v:
113            datamodel = datastructure.getDataModel()
114            datamodel[self.fields[0]] = v
115
116        return not err
117
118InitializeClass(WAeUPPasswordWidget)
119
120widgetRegistry.register(WAeUPPasswordWidget)
121###)
122
123class CPSSelectWidgetForRecord(CPSSelectWidget): ###(
124    """Select widget. with record names"""
125    meta_type = 'Select Widget for Records'
126
127    field_types = ('CPS String Field',)
128    field_inits = ({'is_searchabletext': 1,},)
129
130    _properties = CPSSelectWidget._properties + (
131        {'id': 'record_id', 'type': 'string', 'mode': 'w',
132         'label': 'Record Id', 'is_required' : 1},
133        )
134
135    def render(self, mode, datastructure, **kw):
136        """Render in mode from datastructure."""
137        value = datastructure[self.getWidgetId()]
138        vocabulary = self._getVocabulary(datastructure)
139        portal = getToolByName(self, 'portal_url').getPortalObject()
140        cpsmcat = portal.translation_service
141        if mode == 'view':
142            if self.translated:
143                return escape(cpsmcat(vocabulary.getMsgid(value, value)).encode('ISO-8859-15', 'ignore'))
144            else:
145                return escape(vocabulary.get(value, value))
146        elif mode == 'edit':
147            html_widget_id = self.getHtmlWidgetId()
148            res = renderHtmlTag('select',
149                                name='%s.%s:records' % (self.record_id,html_widget_id),
150                                id=html_widget_id)
151            in_selection = 0
152            for k, v in vocabulary.items():
153                if self.translated:
154                    kw = {'value': k,
155                          'contents': cpsmcat(vocabulary.getMsgid(k, k)).encode('ISO-8859-15', 'ignore')
156                          }
157                else:
158                    kw = {'value': k, 'contents': v}
159                if value == k:
160                    kw['selected'] = 'selected'
161                    in_selection = 1
162                res += renderHtmlTag('option', **kw)
163            if value and not in_selection:
164                kw = {'value': value, 'contents': 'invalid: '+ str(value),
165                      'selected': 'selected'}
166                res += renderHtmlTag('option', **kw)
167            res += '</select>'
168            return res
169        raise RuntimeError('unknown mode %s' % mode)
170
171InitializeClass(CPSSelectWidgetForRecord)
172
173widgetRegistry.register(CPSSelectWidgetForRecord)
174
175###)
176
177class CPSStringWidgetForRecord(CPSStringWidget): ###(
178    """String widget."""
179    meta_type = 'String Widget For Record'
180
181    field_types = ('CPS String Field',)
182    field_inits = ({'is_searchabletext': 1,},)
183    _properties = CPSStringWidget._properties + (
184        {'id': 'record_id', 'type': 'string', 'mode': 'w',
185         'label': 'Record Id', 'is_required' : 1},
186        )
187
188    def render(self, mode, datastructure, **kw):
189        """Render in mode from datastructure."""
190        value = datastructure[self.getWidgetId()]
191        if mode == 'view':
192            return escape(value)
193        elif mode == 'edit':
194            # XXX TODO should use an other name than kw !
195            # XXX change this everywhere
196            html_widget_id = self.getHtmlWidgetId()
197            kw = {'type': 'text',
198                  'id'  : html_widget_id,
199                  'name': '%s.%s:records' % (self.record_id,html_widget_id),
200                  'value': escape(value),
201                  'size': self.display_width,
202                  }
203            if self.size_max:
204                kw['maxlength'] = self.size_max
205            return renderHtmlTag('input', **kw)
206        raise RuntimeError('unknown mode %s' % mode)
207
208InitializeClass(CPSStringWidgetForRecord)
209
210widgetRegistry.register(CPSStringWidgetForRecord)
211
212###)
213
214class CertificateCourseIdWidget(CPSStringWidget): ###(
215    """ CertificateCourseId Widget"""
216    meta_type = "CertificateCourseId Widget"
217
218    def validate(self, datastructure, **kw):
219        """Validate datastructure and update datamodel."""
220
221        valid = CPSStringWidget.validate(self, datastructure, **kw)
222        if not valid:
223            return 0
224        else:
225            widget_id = self.getWidgetId()
226            value = datastructure[widget_id].upper()
227            err = 0
228            c_ids = [c.id for c in self.portal_catalog({'meta_type': "Course"})]
229            if hasattr(self.aq_parent,value):
230                err = 'Course already exists'
231            elif value not in c_ids:
232                err = 'Course does not exist'
233            if err:
234                datastructure.setError(widget_id, err)
235            else:
236                datamodel = datastructure.getDataModel()
237                datamodel[self.fields[0]] = value
238
239            return not err
240
241InitializeClass(CertificateCourseIdWidget)
242
243widgetRegistry.register(CertificateCourseIdWidget)
244###)
245
246class CourseIdWidget(CPSStringWidget): ###(
247    """ CourseId Widget"""
248    meta_type = "CourseId Widget"
249
250    def validate(self, datastructure, **kw):
251        """Validate datastructure and update datamodel."""
252
253        valid = CPSStringWidget.validate(self, datastructure, **kw)
254        if not valid:
255            return 0
256        else:
257            widget_id = self.getWidgetId()
258            value = datastructure[widget_id].upper()
259            err = 0
260            res = self.courses_catalog(code = value)
261            if len(res) > 0:
262                err = 'Course already exists'
263            if err:
264                datastructure.setError(widget_id, err)
265            else:
266                datamodel = datastructure.getDataModel()
267                datamodel[self.fields[0]] = value
268
269            return not err
270
271InitializeClass(CourseIdWidget)
272
273widgetRegistry.register(CourseIdWidget)
274
275
276###)
277
278class WAeUPStudyModeWidget(CPSSelectWidget): ###(
279    """WAeUP StudyMode Widget."""
280    meta_type = 'WAeUP StudyMode Widget'
281    vocabulary = 'entry_modes'
282
283    def _getStudyModes(self):
284        voc = getattr(self.portal_vocabularies,self.vocabulary)
285        d = {}
286        for k,v in voc.items():
287            d[k] = v
288        return d
289
290    def validate(self, datastructure, **kw):
291        """Validate datastructure and update datamodel."""
292        widget_id = self.getWidgetId()
293        value = datastructure[widget_id]
294        try:
295            v = str(value)
296        except ValueError:
297            datastructure.setError(widget_id, "'%s' not a valid session key" % value)
298            return 0
299        studymodes = self._getStudyModes()
300        if not value:
301            v = value = 'ume_ft'
302        #import pdb;pdb.set_trace()
303        if not studymodes.has_key(value):
304            datastructure.setError(widget_id, "'%s' not a valid session key" % v)
305            return 0
306        if self.is_required and not len(v):
307            datastructure.setError(widget_id, "session key required")
308            return 0
309
310        datamodel = datastructure.getDataModel()
311        datamodel[self.fields[0]] = v
312        return 1
313
314    def render(self, mode, datastructure, **kw):
315        """Render in mode from datastructure."""
316        value = datastructure[self.getWidgetId()]
317        studymodes = self._getStudyModes()
318        if mode == 'view':
319            return escape(studymodes.get(value, value))
320        elif mode == 'edit':
321            html_widget_id = self.getHtmlWidgetId()
322            res = renderHtmlTag('select', name=html_widget_id, id=html_widget_id)
323            in_selection = 0
324            vocabulary_items = studymodes.items()
325            if self.sorted:
326                vocabulary_items.sort(key=operator.itemgetter(1))
327            for k, v in vocabulary_items:
328                kw = {'value': k, 'contents': v}
329                if value == k:
330                    kw['selected'] = 'selected'
331                    in_selection = 1
332                res += renderHtmlTag('option', **kw)
333            if value and not in_selection:
334                kw = {'value': value, 'contents': 'invalid: '+ str(value),
335                      'selected': 'selected'}
336                res += renderHtmlTag('option', **kw)
337            res += '</select>'
338            return res
339        raise RuntimeError('unknown mode %s' % mode)
340
341InitializeClass(WAeUPStudyModeWidget)
342
343widgetRegistry.register(WAeUPStudyModeWidget)
344
345###)
346
347class WAeUPSessionWidget(CPSSelectWidget): ###(
348    """WAeUP Session Widget for import only"""
349    meta_type = 'WAeUP Session Widget'
350
351    def _getSessions(self):
352        current_year = DateTime().year()
353        d = {'': ''}
354        for y in range(current_year - 10,current_year + 1):
355            d['%s' % str(y)[-2:]] = '%4d/%4d' % (y,y+1)
356        return d
357
358    def validate(self, datastructure, **kw):
359        """Validate datastructure and update datamodel."""
360        widget_id = self.getWidgetId()
361        value = datastructure[widget_id]
362        try:
363            v = str(value)
364        except ValueError:
365            datastructure.setError(widget_id, "'%s' not a valid session key" % value)
366            return 0
367
368        if len(v) == 1:
369            v = value = '0%c' % v
370        elif len(v) == 9:
371            v = value[2:4]
372        elif not value:
373            v = ''
374        sessions = self._getSessions()
375        #import pdb;pdb.set_trace()
376        if not sessions.has_key(v):
377            datastructure.setError(widget_id, "'%s' not a valid session key" % v)
378            return 0
379        if self.is_required and not len(v):
380            datastructure.setError(widget_id, "session key required")
381            return 0
382
383        datamodel = datastructure.getDataModel()
384        datamodel[self.fields[0]] = v
385        return 1
386
387    # rendering is not used, instead we use a select widget with dynamic vocabulary
388    def render(self, mode, datastructure, **kw):
389        """Render in mode from datastructure."""
390        value = datastructure[self.getWidgetId()]
391        sessions = self._getSessions()
392        if mode == 'view':
393            return escape(sessions.get(value, value))
394        elif mode == 'edit':
395            html_widget_id = self.getHtmlWidgetId()
396            res = renderHtmlTag('select', name=html_widget_id, id=html_widget_id)
397            in_selection = 0
398            vocabulary_items = sessions.items()
399            if self.sorted:
400                vocabulary_items.sort(key=operator.itemgetter(0))
401            for k, v in vocabulary_items:
402                kw = {'value': k, 'contents': v}
403                if value == k:
404                    kw['selected'] = 'selected'
405                    in_selection = 1
406                res += renderHtmlTag('option', **kw)
407            if value and not in_selection:
408                kw = {'value': value, 'contents': 'invalid: '+ str(value),
409                      'selected': 'selected'}
410                res += renderHtmlTag('option', **kw)
411            res += '</select>'
412            return res
413        raise RuntimeError('unknown mode %s' % mode)
414
415InitializeClass(WAeUPSessionWidget)
416
417widgetRegistry.register(WAeUPSessionWidget)
418
419###)
420
421class WAeUPLevelWidget(CPSSelectWidget): ###(
422    """WAeUP Level Widget."""
423    meta_type = 'WAeUP Level Widget'
424
425    def _getLevels(self):
426        d = {'':'','000':'Pre-Studies'}
427        for y in range(100,800,100):
428            d['%s' % str(y)] = 'Year %1d (%3d Level)' % (y/100,y)
429        return d
430
431    def validate(self, datastructure, **kw):
432        """Validate datastructure and update datamodel."""
433        widget_id = self.getWidgetId()
434        value = datastructure[widget_id]
435        try:
436            v = str(value)
437        except ValueError:
438            datastructure.setError(widget_id, "'%s' not a valid level key" % value)
439            return 0
440
441        # if not value:
442        #     v = value = '100'
443        #import pdb;pdb.set_trace()
444        levels = self._getLevels()
445        if not levels.has_key(value):
446            datastructure.setError(widget_id, "'%s' not a valid level" % v)
447            return 0
448        # if self.is_required and len(v) == 0:
449        #     datastructure.setError(widget_id, "level key required")
450        #     return 0
451
452        datamodel = datastructure.getDataModel()
453        datamodel[self.fields[0]] = v
454        return 1
455
456    def render(self, mode, datastructure, **kw):
457        """Render in mode from datastructure."""
458        value = datastructure[self.getWidgetId()]
459        levels = self._getLevels()
460        if mode == 'view':
461            return escape(levels.get(value, value))
462        elif mode == 'edit':
463            html_widget_id = self.getHtmlWidgetId()
464            res = renderHtmlTag('select', name=html_widget_id, id=html_widget_id)
465            in_selection = 0
466            vocabulary_items = levels.items()
467            if self.sorted:
468                vocabulary_items.sort(key=operator.itemgetter(0))
469            for k, v in vocabulary_items:
470                kw = {'value': k, 'contents': v}
471                if value == k:
472                    kw['selected'] = 'selected'
473                    in_selection = 1
474                res += renderHtmlTag('option', **kw)
475            if value and not in_selection:
476                kw = {'value': value, 'contents': 'invalid: '+ str(value),
477                      'selected': 'selected'}
478                res += renderHtmlTag('option', **kw)
479            res += '</select>'
480            return res
481        raise RuntimeError('unknown mode %s' % mode)
482
483InitializeClass(WAeUPLevelWidget)
484
485widgetRegistry.register(WAeUPLevelWidget)
486
487###)
488
489class WAeUPVerdictWidget(CPSSelectWidget): ###(
490    """WAeUP Verdict Widget."""
491    meta_type = 'WAeUP Verdict Widget'
492
493    # XXX make a menu for the vocabulary.
494    vocabulary = 'verdicts'
495
496    # Associating the widget label with an input area to improve the widget
497    # accessibility.
498    has_input_area = True
499
500    def _getVerdicts(self,datastructure):
501        voc = getattr(self.portal_vocabularies,self.vocabulary)
502        d = {}
503        for k,v in voc.items():
504            d[k] = v
505        return d
506
507    def validate(self, datastructure, **kw):
508        """Validate datastructure and update datamodel."""
509        widget_id = self.getWidgetId()
510        value = datastructure[widget_id]
511        try:
512            v = str(value)
513        except ValueError:
514            datastructure.setError(widget_id, "'%s' not a valid verdict key" % value)
515            return 0
516        #import pdb;pdb.set_trace()
517        verdicts = self._getVerdicts(datastructure)
518        if not value:
519            v = value = verdicts['']
520        if not verdicts.has_key(value):
521            datastructure.setError(widget_id, "'%s' not a valid verdict key" % v)
522            return 0
523        # if self.is_required and not len(v):
524        #     datastructure.setError(widget_id, "verdict required")
525        #     return 0
526
527        datamodel = datastructure.getDataModel()
528        datamodel[self.fields[0]] = v
529        return 1
530
531    def render(self, mode, datastructure, **kw):
532        """Render in mode from datastructure."""
533        value = datastructure[self.getWidgetId()]
534        verdicts = self._getVerdicts(datastructure)
535        if mode == 'view':
536            return escape(verdicts.get(value, value))
537        elif mode == 'edit':
538            html_widget_id = self.getHtmlWidgetId()
539            res = renderHtmlTag('select', name=html_widget_id, id=html_widget_id)
540            in_selection = 0
541            vocabulary_items = verdicts.items()
542            if self.sorted:
543                vocabulary_items.sort(key=operator.itemgetter(1))
544            for k, v in vocabulary_items:
545                kw = {'value': k, 'contents': v}
546                if value == k:
547                    kw['selected'] = 'selected'
548                    in_selection = 1
549                res += renderHtmlTag('option', **kw)
550            if value and not in_selection:
551                kw = {'value': value, 'contents': 'invalid: '+ str(value),
552                      'selected': 'selected'}
553                res += renderHtmlTag('option', **kw)
554            res += '</select>'
555            return res
556        raise RuntimeError('unknown mode %s' % mode)
557
558InitializeClass(WAeUPVerdictWidget)
559
560widgetRegistry.register(WAeUPVerdictWidget)
561
562###)
563
564class WAeUPLGAWidget(CPSSelectWidget): ###(
565    """WAeUP LGA Widget."""
566    meta_type = 'WAeUP LGA Widget'
567    _properties = CPSSelectWidget._properties + (
568        {'id': 'state_field', 'type': 'string', 'mode': 'w',
569         'label': 'Name of the state field'},
570         {'id': 'lga_field', 'type': 'string', 'mode': 'w',
571         'label': 'Name of the lga field (without state)'},
572         )
573    state_field = "state"
574    lga_field = "lga"
575
576    # XXX make a menu for the vocabulary.
577    vocabulary = 'local_gov_areas'
578
579    # Associating the widget label with an input area to improve the widget
580    # accessibility.
581    has_input_area = True
582
583    def _getLGAs(self):
584        if getattr(self,'_v_states',None) is not None and\
585           getattr(self,'_v_lgas',None) is not None and\
586           getattr(self,'_v_d',None) is not None and\
587           getattr(self,'_v_word_dict',None) is not None:
588            return (self._v_d,self._v_states,self._v_lgas,self._v_word_dict)
589        mapping = self.waeup_tool.getStatesLgas()
590        self._v_d = mapping['lga_dict']
591        self._v_states = mapping['states']
592        self._v_lgas = mapping['lgas']
593        self._v_word_dict = mapping['word_dict']
594        return (self._v_d,self._v_states,self._v_lgas,self._v_word_dict)
595
596
597    def validate(self, datastructure, **kw):
598        """Validate datastructure and update datamodel."""
599        widget_id = self.getWidgetId()
600        value = datastructure[widget_id]
601        #import pdb;pdb.set_trace()
602        try:
603            v = str(value)
604        except ValueError:
605            datastructure.setError(widget_id, "'%s' not a valid lga key" % value)
606            return 0
607        v = v.lower()
608        combined,states,lgas,word_dict = self._getLGAs()
609        datamodel = datastructure.getDataModel()
610        if self.state_field and self.lga_field:
611            v = ' '.join((datastructure.get(self.state_field,""),
612                              datastructure.get(self.lga_field,"")))
613        state_lga = self.waeup_tool.findLga(v,word_dict)
614        if not state_lga:
615            if self.is_required:
616                datastructure.setError(widget_id, "'%s' not a valid lga key" % v)
617                #datastructure.setError(widget_id, "%s required" % widget_id)
618                return 0
619            else:
620                state_lga = v
621        datamodel[self.fields[0]] = state_lga
622        return 1
623
624    def render(self, mode, datastructure, **kw):
625        """Render in mode from datastructure."""
626        w_id = self
627        value = datastructure[self.getWidgetId()]
628        lgas,x,y = self._getLGAs(datastructure)
629        if mode == 'view':
630            return escape(lgas.get(value, value))
631        elif mode == 'edit':
632            html_widget_id = self.getHtmlWidgetId()
633            res = renderHtmlTag('select', name=html_widget_id, id=html_widget_id)
634            in_selection = 0
635            vocabulary_items = lgas.items()
636            # if self.sorted:
637            #     vocabulary_items.sort(key=operator.itemgetter(1))
638            for k, v in vocabulary_items:
639                kw = {'value': k, 'contents': v}
640                if value == k:
641                    kw['selected'] = 'selected'
642                    in_selection = 1
643                res += renderHtmlTag('option', **kw)
644            if value and not in_selection:
645                kw = {'value': value, 'contents': 'invalid: '+ str(value),
646                      'selected': 'selected'}
647                res += renderHtmlTag('option', **kw)
648            res += '</select>'
649            return res
650        raise RuntimeError('unknown mode %s' % mode)
651
652InitializeClass(WAeUPLGAWidget)
653
654widgetRegistry.register(WAeUPLGAWidget)
655
656###)
657
658class WAeUPReservedRoomsWidget(CPSStringWidget): ###(
659    """ WAeUPReservedRooms Widget"""
660    meta_type = "WAeUPReservedRooms Widget"
661
662    def validate(self, datastructure, **kw):
663        """Validate datastructure and update datamodel."""
664        import re
665        valid = CPSStringWidget.validate(self, datastructure, **kw)
666        if not valid:
667            return 0
668        else:
669            widget_id = self.getWidgetId()
670            value = datastructure[widget_id]
671            err = 0
672            try:
673                reserved = [(r.split('/')[0],int(r.split('/')[1])) for r in re.split(',|\.| ',value)
674                                     if r]
675            except (ValueError,IndexError),msg:
676                err = str(msg)
677            if err:
678                datastructure.setError(widget_id, err)
679            else:
680                datamodel = datastructure.getDataModel()
681                datamodel[self.fields[0]] = value
682            return not err
683
684InitializeClass(WAeUPReservedRoomsWidget)
685
686widgetRegistry.register(WAeUPReservedRoomsWidget)
687###)
688
689class WAeUPIdWidget(CPSStringWidget): ###(
690    """ WAeUPId Widget"""
691    meta_type = "WAeUPId Widget"
692
693    def validate(self, datastructure, **kw):
694        """Validate datastructure and update datamodel."""
695        mode = kw.get('mode','create')
696        valid = CPSStringWidget.validate(self, datastructure, **kw)
697        id_pat_str = r"\S"
698        inv_id_pat = re.compile(r"^%s$" % id_pat_str)
699        if not valid:
700            return 0
701        else:
702            portal_type_query = {'query':['Faculty',
703                                          'Department',
704                                          'Course',
705                                          'Certificate',
706                                          #'CertificateCourse',
707                                         ]}
708            widget_id = self.getWidgetId()
709            value = datastructure[widget_id]  #.upper()  is not necessary here because it's also done in waeup_document_create_do
710            err = 0
711            mapping = {}
712            if len(value.split()) > 1:
713                err = 'Invalid Id, Id contains space(s).'
714            elif mode == "create" and\
715                          self.portal_catalog(portal_type=portal_type_query,id=value):
716                brain = self.portal_catalog(portal_type=portal_type_query,id=value)[0]
717                err = 'An ${portal_type} object with the Id ${id} already exists at ${path}.'
718                mapping = {'portal_type': brain.portal_type,
719                           'id': value,
720                           'path': brain.getPath(),
721                           }
722            if err:
723                datastructure.setError(widget_id, err, mapping)
724            else:
725                datamodel = datastructure.getDataModel()
726                datamodel[self.fields[0]] = value
727
728            return not err
729
730InitializeClass(WAeUPIdWidget)
731
732widgetRegistry.register(WAeUPIdWidget)
733
734
735###)
736
737class StudyCourseWidget(CPSStringWidget): ###(
738    """ StudyCourse Widget"""
739    meta_type = "StudyCourse Widget"
740
741    def validate(self, datastructure, **kw):
742        """Validate datastructure and update datamodel."""
743        #from Products.zdb import set_trace
744        #set_trace()
745##        valid = CPSStringWidget.validate(self, datastructure, **kw)
746##        if not valid:
747##            return 0
748        widget_id = self.getWidgetId()
749        #value = makeCertificateCode(datastructure[widget_id]).upper()
750        value = datastructure[widget_id].upper()
751        id_pat_str = r"\S"
752        inv_id_pat = re.compile(r"^%s$" % id_pat_str)
753        err = 0
754        if len(value.split()) > 1:
755            err = 'Invalid Id, Id contains space(s).'
756        elif not self.portal_catalog(portal_type='Certificate',id=value):
757            err = 'No such certificate'
758        if err:
759            datastructure.setError(widget_id, err)
760        else:
761            datamodel = datastructure.getDataModel()
762            datamodel[self.fields[0]] = value
763        return not err
764
765InitializeClass(StudyCourseWidget)
766
767widgetRegistry.register(StudyCourseWidget)
768###)
769
770class VocabularyOnTheFly: ###(
771    def __init__(self, tuples):
772        """a nonpersistent vocabulary (copy from CPSSchemas.Vocabulary.Vocabulary).
773        Allowed parameter syntaxes is:
774          - Vocabulary((('foo', "Foo", 'label_foo'), ('bar', "Bar", 'label_bar')))
775            Same as first with message ids (msgids) that can be used for i18n
776        """
777        l = []
778        d = {}
779        m = {}
780        # We suppose that initial vocabulary is sorted
781        # Vocabulary((('foo', "Foo", 'label_foo'), ('bar', "Bar", 'label_bar')))
782        for k, v, msgid in tuples:
783            l.append(k)
784            d[k] = v
785            m[k] = msgid
786        self._list = l
787        self._dict = d
788        self._msgids = m
789
790    def __getitem__(self, key):
791        """Get a label for a key."""
792        return self._dict[key]
793
794    def get(self, key, default=None):
795        """Get a label for a key, default to None."""
796        try:
797            v = self._dict.get(key, default)
798        except TypeError:
799            # XXX temporary fix, don't know why sometime rendering try to do
800            # get([]) that returning a typeError
801            return ''
802        return v
803
804    def getMsgid(self, key, default=None):
805        """Get a msgid for a key, default to None."""
806        return self._msgids.get(key, default)
807
808    def has_key(self, key):
809        """Test if a key is present."""
810        return self._dict.has_key(key)
811
812    def keys(self):
813        """Get the ordered list of keys."""
814        return self._list[:]
815
816    def items(self):
817        """Get the ordered list of (key, value)."""
818        return [(key, self._dict.get(key)) for key in self._list]
819
820    def values(self):
821        """Get the ordered list of values."""
822        return [self._dict.get(key) for key in self._list]
823
824    def keysSortedBy(self, crit='id'):
825        """Return a keys list sorted on a criterium
826
827        Crit is one of 'id', 'label' or 'i18n'.
828        """
829
830        if crit == 'label':
831            l = [(x[1], x[0]) for x in self.items()]
832            l.sort()
833            return [x[1] for x in l]
834        elif crit == 'i18n':
835            portal = getToolByName(self, 'portal_url').getPortalObject()
836            cpsmcat = portal.translation_service
837            l = [(cpsmcat(self.getMsgid(key)).encode('ISO-8859-15', 'ignore'),
838                  key) for key in self.keys()]
839            l.sort()
840            return [x[1] for x in l]
841        else:
842            return self.keys()
843###)
844
845class ApplicationCourseWidget(CPSSelectWidget): ###(
846    """ ApplicationCourse Widget"""
847    meta_type = "Application Course Widget"
848
849    def _getVocabulary(self,datastructure=None):
850        if self.REQUEST.traverse_subpath:
851            screening_type = self.REQUEST.traverse_subpath[0].lower()
852        else:
853            screening_type = 'all'
854        if screening_type in ("all","cest","sandwich","pg"):
855            application_category = screening_type
856        else:
857            application_category = "basic"
858        if not hasattr(self,'_v_certificates_docs'):
859            res = self.portal_catalog_real.search({'meta_type': "Certificate"})
860            d = {}
861            for cert in res:
862                c = cert.getObject().getContent()
863                if getattr(c,'application_category',''):
864                    d[cert.getId] = c
865            self._v_certificates_docs = d
866        l  = [('','','')]
867        #l = []
868        for k,d in self._v_certificates_docs.items():
869            if application_category == "all":
870                l  += (k,self._v_certificates_docs[k].title,k),
871            else:
872                if getattr(d,'application_category','') == application_category:
873                    l  += (k,self._v_certificates_docs[k].title,k),
874        #import ipdb;ipdb.set_trace()
875        return VocabularyOnTheFly(l)
876
877InitializeClass(ApplicationCourseWidget)
878
879widgetRegistry.register(ApplicationCourseWidget)
880###)
881
882class JambRegNoWidget(CPSStringWidget): ###(
883    """ JambRegNo Widget"""
884    meta_type = "JambRegNo Widget"
885    _properties = CPSStringWidget._properties + (
886        {'id': 'catalog', 'type': 'string', 'mode': 'w',
887         'label': 'Catalog to search'},
888         {'id': 'reference', 'type': 'string', 'mode': 'w',
889         'label': 'Reference Field'},
890         )
891    #catalog = "portal_pumeresults" #the catalog to search for jamb_reg_no
892    reference = ""
893    digits = 8
894    digits_str = "N"*digits
895    letters = 2
896    letters_str = "L"*letters
897    def validate(self, datastructure, **kw):
898        """Validate datastructure and update datamodel."""
899        valid = CPSStringWidget.validate(self, datastructure, **kw)
900        reg_no_catalog = getattr(self,self.catalog)
901        widget_id = self.getWidgetId()
902        value = datastructure[widget_id].upper()
903        err = 0
904        #import pdb;pdb.set_trace()
905        if kw.has_key('mode'):
906            mode = kw['mode']
907        else:
908            mode = "edit"
909        if not valid:
910            err = 'Invalid registration number'
911        elif self.reference == '':
912            #s = getStudentByRegNo(self,value)
913            student_record = reg_no_catalog(jamb_reg_no = value)
914            if len(student_record) < 1:
915                err = 'No student record with this registration number'
916            elif self.catalog == "students_catalog" and student_record[0].review_state not in ('student_created','admitted'):
917                err = 'Admission checking not allowed (wrong registration state)'
918            else:
919                datastructure['pume'] = student_record[0]
920        elif mode == 'add':
921            pass
922        elif self.reference != '' and self.catalog == "applicants_catalog":
923            res = reg_no_catalog.searchResults({"%s" % self.reference: value})
924            if len(res) != 1:
925                err = 'No record with this registration number'
926            else:
927                datastructure['record'] = res[0]
928        else:
929            record = datastructure[self.reference]
930            #jamb_reg_no = getattr(record,widget_id)
931            jamb_reg_no = record.Entryregno
932            if jamb_reg_no != value:
933                err = 'Registration number does not match.'
934        if err:
935            datastructure.setError(widget_id, err)
936        else:
937            datamodel = datastructure.getDataModel()
938            datamodel[self.fields[0]] = value
939        return not err
940
941InitializeClass(JambRegNoWidget)
942
943widgetRegistry.register(JambRegNoWidget)
944###)
945
946class SecretWidget(CPSStringWidget): ###(
947    """ Secret Widget"""
948    meta_type = "Secret Widget"
949    _properties = CPSStringWidget._properties + (
950        {'id': 'reference', 'type': 'string', 'mode': 'w',
951         'label': 'Reference Record'},
952         {'id': 'check_fields', 'type': 'tokens', 'mode': 'w',
953         'label': 'Fields to check'},
954         )
955    reference = "student"
956    matric_no_catalog = 'returning_import'
957    check_fields = ("Firstname", "Middlename","Lastname")
958    def validate(self, datastructure, **kw):
959        """Validate datastructure and update datamodel."""
960        logger = logging.getLogger('Widgets.SecretWidget.validate')
961        valid = CPSStringWidget.validate(self, datastructure, **kw)
962        widget_id = self.getWidgetId()
963        value = datastructure[widget_id].upper()
964        err = 0
965        record = datastructure.get(self.reference,None)
966        #import pdb;pdb.set_trace()
967        if not valid or len(value) < 2:
968            err = 'Invalid string'
969        elif not record or datastructure.errors:
970            err = 0
971        else:
972            found = False
973            cvs = []
974            for field in self.check_fields:
975                cv = getattr(record,field).upper()
976                if len(cv.split()) > 1:
977                    for splited in cv.split():
978                        cvs.append(splited.strip())
979                else:
980                    cvs.append(cv.strip(),)
981            for cv in cvs:
982                if cv  == value.strip().upper():
983                    found = True
984                    break
985            matric_no = record.matric_no
986            name = " ".join(cvs)
987            if not found:
988                logger.info('%(matric_no)s did not find %(value)s in %(name)s' % vars())
989                err = 'No name does match.'
990            else:
991                logger.info('%(matric_no)s found %(value)s in %(name)s' % vars())
992        if err:
993            datastructure.setError(widget_id, err)
994        else:
995            datamodel = datastructure.getDataModel()
996            datamodel[self.fields[0]] = value
997        return not err
998
999InitializeClass(SecretWidget)
1000
1001widgetRegistry.register(SecretWidget)
1002###)
1003
1004class WAeUPSexWidget(CPSBooleanWidget): ###(
1005    """WAeUP sex widget."""
1006    meta_type = 'WAeUP Sex Widget'
1007
1008    def validate(self, datastructure, **kw):
1009        """Validate datastructure and update datamodel."""
1010        value = datastructure[self.getWidgetId()]
1011
1012        if self.render_format not in self.render_formats:
1013            self.render_format = 'select'
1014
1015        female = value in ('F','f','Female','female',"True",True)
1016        male = value in ('M','m','Male','male','False',False)
1017        if not female and not male:
1018            datastructure.setError(self.getWidgetId(),
1019                                   "invalid sex %s" % value)
1020            return 0
1021        elif female:
1022            v = True
1023        else:
1024            v = False
1025        datamodel = datastructure.getDataModel()
1026        datamodel[self.fields[0]] = v
1027        return 1
1028
1029InitializeClass(WAeUPSexWidget)
1030
1031widgetRegistry.register(WAeUPSexWidget)
1032
1033###)
1034
1035class WAeUPBooleanWidget(CPSBooleanWidget): ###(
1036    """WAeUP boolean widget."""
1037    meta_type = 'WAeUP Boolean Widget'
1038
1039    def validate(self, datastructure, **kw):
1040        """Validate datastructure and update datamodel."""
1041        value = datastructure[self.getWidgetId()]
1042
1043        if self.render_format not in self.render_formats:
1044            self.render_format = 'select'
1045        true = value.upper() in ('T','1','TRUE','WAHR',True)
1046        false = value.upper() in ('F','0','FALSE','FALSCH',False)
1047        if not true and not false:
1048            datastructure.setError(self.getWidgetId(),
1049                                   "invalid boolean %s" % value)
1050            return 0
1051        elif true:
1052            v = True
1053        else:
1054            v = False
1055        datamodel = datastructure.getDataModel()
1056        datamodel[self.fields[0]] = v
1057        return 1
1058
1059InitializeClass(WAeUPBooleanWidget)
1060
1061widgetRegistry.register(WAeUPBooleanWidget)
1062
1063###)
1064
1065class MatricNoWidget(CPSStringWidget): ###(
1066    """ MatricNo Widget"""
1067    meta_type = "MatricNo Widget"
1068
1069    _properties = CPSStringWidget._properties + (
1070        {'id': 'matric_no_catalog', 'type': 'string', 'mode': 'w',
1071         'label': 'Catalog to search for MatricNo'},
1072        { 'id': 'results_catalog', 'type': 'string', 'mode': 'w',
1073         'label': 'Results Catalog'},
1074         )
1075    matric_no_catalog = "" #the catalog to search for matric_no
1076    results_catalog = "results_import" #results catalog
1077
1078    def validate(self, datastructure, **kw):
1079        """Validate datastructure and update datamodel."""
1080        #import pdb;pdb.set_trace()
1081        valid = CPSStringWidget.validate(self, datastructure, **kw)
1082        logger = logging.getLogger('Widgets.MatricNoWidget.validate')
1083        returning = getattr(self,self.matric_no_catalog)
1084        results = getattr(self,self.results_catalog,None)
1085        err = 0
1086        widget_id = self.getWidgetId()
1087        value = datastructure[widget_id]
1088        if not valid or not value:
1089            err = 'Invalid string'
1090            logger.info('Invalid matric_no string %s' % value)
1091        else:
1092            value = value.upper()
1093            datastructure['student'] = None
1094            while not err:
1095                res = returning(matric_no = value)
1096                if len(res) < 1:
1097                    logger.info('matric_no %s not found' % value)
1098                    err = 'No student with this matriculation number.'
1099                    break
1100                datastructure['student'] = res[0]
1101                if results is not None:
1102                    res = results(matric_no = value)
1103                    if len(res) < 1:
1104                        err = 'No results for this matriculation number'
1105                        continue
1106                    datastructure['results'] = res
1107                break
1108        if err:
1109            datastructure.setError(widget_id, err)
1110        else:
1111            datamodel = datastructure.getDataModel()
1112            datamodel[self.fields[0]] = value
1113        return not err
1114
1115InitializeClass(MatricNoWidget)
1116
1117widgetRegistry.register(MatricNoWidget)
1118###)
1119
1120class StudentIdWidget(CPSStringWidget): ###(
1121    """ StudentId Widget"""
1122    meta_type = "StudentId Widget"
1123    def validate(self, datastructure, **kw):
1124        """Validate datastructure and update datamodel."""
1125        valid = CPSStringWidget.validate(self, datastructure, **kw)
1126        logger = logging.getLogger('Widgets.StudentIdWidget.validate')
1127        #import pdb;pdb.set_trace()
1128        s_cat = self.students_catalog
1129        err = 0
1130        widget_id = self.getWidgetId()
1131        value = datastructure[widget_id]
1132        if not valid or not value:
1133            err = 'Invalid Id string'
1134            logger.info('Invalid id string %s' % value)
1135            datastructure['student'] = None
1136        else:
1137            value = value.upper()
1138            res = s_cat(id = value)
1139            if not res:
1140                logger.info('Student id %s not found' % value)
1141                err = 'No student with this Id'
1142                datastructure['student'] = None
1143            else:
1144                datastructure['student'] = res[0]
1145        if err:
1146            datastructure.setError(widget_id, err)
1147        else:
1148            datamodel = datastructure.getDataModel()
1149            datamodel[self.fields[0]] = value
1150        return not err
1151
1152InitializeClass(StudentIdWidget)
1153
1154widgetRegistry.register(StudentIdWidget)
1155###)
1156
1157class WAeUPMultilineResultsWidget(CPSStringWidget): ###(
1158    """ WAeUPMultilineResults Widget"""
1159    meta_type = "WAeUp Multiline Results Widget"
1160    _properties = CPSWidget._properties + (
1161        {'id': 'nr_of_lines', 'type': 'int', 'mode': 'w',
1162         'label': 'Nr of Lines'},
1163         )
1164    nr_of_lines = 5
1165    def prepare(self, datastructure, **kw): ###(
1166        """Prepare datastructure from datamodel."""
1167        datamodel = datastructure.getDataModel()
1168        #import pdb;pdb.set_trace()
1169        widget_id = self.getWidgetId()
1170        v = datamodel[self.fields[0]]
1171        if type(v) is ListType and v:
1172            nr_results = len(v)
1173        else:
1174            v = []
1175            nr_results = 0
1176        count = 1
1177        for s,g in v:
1178            wid = "%s%02d"% (widget_id,count)
1179            datastructure[wid+'_s'] = s
1180            datastructure[wid+'_g'] = g
1181            count += 1
1182        if nr_results < self.nr_of_lines:
1183            for line in range(nr_results,self.nr_of_lines):
1184                v.append(('',''))
1185                wid = "%s%02d"% (widget_id,line)
1186                datastructure[wid+'_s'] = ''
1187                datastructure[wid+'_g'] = ''
1188        datastructure[widget_id] = v
1189        datastructure[widget_id+'_s'] = ''
1190        datastructure[widget_id+'_g'] = ''
1191    ###)
1192
1193    def validate(self, datastructure, **kw): ###(
1194        """Validate datastructure and update datamodel."""
1195        #import pdb;pdb.set_trace()
1196        widget_id = self.getWidgetId()
1197        err = 0
1198        lines = []
1199        for line in range(1,30):
1200            wid = "%s%02d"% (widget_id,line)
1201            if not datastructure.has_key(wid+'_s'):
1202                break
1203            lines.append((datastructure[wid+'_s'].strip(),
1204                         datastructure[wid+'_g'].strip()))
1205
1206        s = datastructure[widget_id+'_s'].strip()
1207        g = datastructure[widget_id+'_g'].strip()
1208        if s and g:
1209            lines.append((s,g))
1210        active = []
1211        for s,g in lines:
1212            if g != "":
1213                active.append((s,g))
1214        if err:
1215            datastructure.setError(widget_id, err)
1216        else:
1217            datamodel = datastructure.getDataModel()
1218            datamodel[self.fields[0]] = active
1219        return not err
1220    ###)
1221
1222    def render(self, mode, datastructure, **kw): ###(
1223        """Render in mode from datastructure."""
1224        render_method = 'widget_waeup_multiline_result_render'
1225        meth = getattr(self, render_method, None)
1226        if meth is None:
1227            raise RuntimeError("Unknown Render Method %s for widget type %s"
1228                               % (render_method, self.getId()))
1229        #import pdb;pdb.set_trace()
1230        datamodel = datastructure.getDataModel()
1231        widget_id = self.getWidgetId()
1232        lines = datamodel[self.fields[0]]
1233        if len(lines) < self.nr_of_lines:
1234            for line in range(len(lines),self.nr_of_lines + 1):
1235                lines.append(('',''))
1236        datastructure[widget_id] = lines
1237        datastructure[widget_id+'_s'] = ''
1238        datastructure[widget_id+'_g'] = ''
1239##        count = 1
1240##        for s,g in v:
1241##            wid = "%s%02d"% (widget_id,count)
1242##            count += 1
1243        return meth(mode=mode,
1244                    datastructure=datastructure,
1245                    )
1246    ###)
1247
1248
1249InitializeClass(WAeUPMultilineResultsWidget)
1250widgetRegistry.register(WAeUPMultilineResultsWidget)
1251###)
1252
1253class WAeUPResultsWidget(CPSStringWidget): ###(
1254    """ WAeUPResults Widget"""
1255    meta_type = "WAeUp Results Widget"
1256
1257    def prepare(self, datastructure, **kw): ###(
1258        """Prepare datastructure from datamodel."""
1259        datamodel = datastructure.getDataModel()
1260        v = datamodel[self.fields[0]]
1261        #import pdb;pdb.set_trace()
1262        widget_id = self.getWidgetId()
1263        datastructure[widget_id] = v
1264        datastructure[widget_id+'_s'] = ''
1265        datastructure[widget_id+'_g'] = ''
1266    ###)
1267
1268    def validate(self, datastructure, **kw): ###(
1269        """Validate datastructure and update datamodel."""
1270        #import pdb;pdb.set_trace()
1271        widget_id = self.getWidgetId()
1272        v = datastructure[widget_id]
1273        if not v:
1274            v = []
1275        err = 0
1276        s = datastructure[widget_id+'_s'].strip()
1277        g = datastructure[widget_id+'_g'].strip()
1278        while 1:
1279            if not s and g:
1280                err = "No subject grade for subject"
1281                break
1282            i = 0
1283            done = False
1284            #import pdb;pdb.set_trace()
1285            for sv,gv in v:
1286                if sv == s:
1287                    done = True
1288                    if not g:
1289                        v.pop(i)
1290                        break
1291                    v[i] = (s,g)
1292                    break
1293                i += 1
1294            if done:
1295                break
1296            if s and g:
1297                if v:
1298                    v += (s,g),
1299                else:
1300                    v = [(s,g),]
1301            break
1302        if err:
1303            datastructure.setError(widget_id, err)
1304        else:
1305            datamodel = datastructure.getDataModel()
1306            datamodel[self.fields[0]] = v
1307            datastructure[widget_id] = v
1308            datastructure[widget_id+'_s'] = s
1309            datastructure[widget_id+'_g'] = g
1310        return not err
1311    ###)
1312
1313    def render(self, mode, datastructure, **kw): ###(
1314        """Render in mode from datastructure."""
1315        render_method = 'widget_waeup_result_render'
1316        meth = getattr(self, render_method, None)
1317        if meth is None:
1318            raise RuntimeError("Unknown Render Method %s for widget type %s"
1319                               % (render_method, self.getId()))
1320        datamodel = datastructure.getDataModel()
1321        widget_id = self.getWidgetId()
1322        datastructure[widget_id+'_s'] = ''
1323        datastructure[widget_id+'_g'] = ''
1324        return meth(mode=mode,
1325                    datastructure=datastructure,
1326                    )
1327    ###)
1328
1329
1330InitializeClass(WAeUPResultsWidget)
1331widgetRegistry.register(WAeUPResultsWidget)
1332###)
1333
1334class ScratchCardPin: ###(
1335    """the ScratchCardPin"""
1336    def __init__(self,prefix,batch_no,number):
1337        if not batch_no and not number:
1338            s = prefix
1339            if len(s) > 3:
1340                prefix,batch_no,number = s[:3],s[3:-10],s[-10:]
1341            else:
1342                prefix,batch_no,number = s,'',''
1343        self.p = prefix
1344        self.b = batch_no
1345        self.n = number
1346
1347    def __str__(self):
1348        return "%s-%s-%s" % (self.p,self.b,self.n)
1349
1350    def __repr__(self):
1351        return "%s%s%s" % (self.p,self.b,self.n)
1352###)
1353
1354class ScratchcardPinWidget(CPSStringWidget): ###(
1355    """ ScratchcardPin Widget"""
1356    meta_type = "Scratchcard Pin Widget"
1357    _properties = CPSWidget._properties + (
1358        {'id': 'prefix', 'type': 'string', 'mode': 'w',
1359         'label': 'Prefix'},
1360         {'id': 'reference', 'type': 'string', 'mode': 'w',
1361         'label': 'Reference Field'},
1362         {'id': 'reuse_pin', 'type': 'boolean', 'mode': 'w',
1363         'label': 'Reuse Application Pin'},
1364        )
1365    prefix = ''
1366    reference = ''
1367    reuse_pin = False
1368
1369    def prepare(self, datastructure, **kw): ###(
1370        """Prepare datastructure from datamodel."""
1371        datamodel = datastructure.getDataModel()
1372        v = datamodel[self.fields[0]]
1373        widget_id = self.getWidgetId()
1374        if v and type(v) is StringType:
1375            try:
1376                p,b,n = v.split('-')
1377                v = ScratchCardPin(p,b,n)
1378            except ValueError:
1379                v = ScratchCardPin(v,'','')
1380        if v:
1381            p = '%s' % v.p
1382            b = '%s' % v.b
1383            n = '%s' % v.n
1384        else:
1385            p = self.prefix
1386            if p.startswith('@'):
1387                p = getattr(self,self.prefix[1:])()
1388            b = n = ''
1389            v = ScratchCardPin(p,b,n)
1390        datastructure[widget_id] = v
1391        datastructure[widget_id+'_p'] = p
1392        datastructure[widget_id+'_b'] = b
1393        datastructure[widget_id+'_n'] = n
1394    ###)
1395
1396    def validate(self, datastructure, **kw): ###(
1397        """Validate datastructure and update datamodel."""
1398        s_logger = logging.getLogger('Widgets.ScratchcardPinWidget.validate')
1399        widget_id = self.getWidgetId()
1400        v = datastructure[widget_id]
1401        #import pdb;pdb.set_trace()
1402        err = 0
1403        mapping = {}
1404        prefix= self.prefix
1405        if prefix.startswith('@'):
1406            prefix= getattr(self,self.prefix[1:])()
1407        b = datastructure[widget_id+'_b'].strip()
1408        n = datastructure[widget_id+'_n'].strip()
1409        pins = self.portal_pins
1410        pin = "%(prefix)s%(b)s%(n)s" % vars()
1411        pin_str = "%(prefix)s-%(b)s-%(n)s" % vars()
1412        do = 1
1413        s_id = str(self.portal_membership.getAuthenticatedMember())
1414        if self.isStaff():
1415            do = 0
1416            err ='You are not a Student. PIN neither checked nor used.'
1417            s_logger.info('%s tried to use scratch card %s' % (s_id,pin_str))
1418        elif len(b) > 1 and b.find('-') > -1:
1419            do = 0
1420            err = 'PIN must not contain "-".'
1421            s_logger.info('%s entered invalid PIN  containing "-"' % (s_id))
1422        elif n.find('-') > -1:
1423            do = 0
1424            err = 'PIN must not contain "-".'
1425            s_logger.info('%s entered invalid PIN  containing "-"' % (s_id))
1426        elif len(n) != 10:
1427            do = 0
1428            err = 'Invalid PIN length'
1429            s_logger.info('%s entered invalid PIN with length %d' % (s_id,len(n)))
1430        elif self.reference == "":
1431            ref = s_id
1432        else:
1433            ref = datastructure[self.reference]
1434            if datastructure.errors:
1435                do = 0
1436                datastructure.setError(widget_id, 'PIN neither checked nor used.')
1437                s_logger.info('%s/%s entered wrong data together with PIN %s' % (s_id,ref,pin_str))
1438            elif prefix == 'APP' and not self.reuse_pin:
1439                res =  self.applicants_catalog(reg_no = ref)
1440                if not res:
1441                    res =  self.applicants_catalog(reg_no = ref.upper())
1442                if res and res[0].pin == pin_str:
1443                    do = 0
1444                    err = 'Application PINs cannot be reused.'
1445                    s_logger.info('%s entered same PIN as for screening application %s' % (s_id,pin_str))
1446
1447        while do:
1448            ok,record = pins.searchAndSetRecord(pin,ref,prefix)
1449            if ok < -2 or ok > 2:
1450                err = 'Unknown error, please report!'
1451                s_logger.info('%s/%s caused unknown error with PIN %s' % (s_id,ref,pin_str))
1452                break
1453            elif ok == -2:
1454                err = 'Service already is activated but with a different PIN.'
1455                s_logger.info('%s/%s repeatedly activated service but with different PIN %s' % (s_id,ref,pin_str))
1456                break
1457            elif ok == -1:
1458                err = 'Invalid PIN'
1459                s_logger.info('%s/%s entered invalid PIN %s' % (s_id,ref,pin_str))
1460                break
1461            if ok == 0:
1462                err = 'PIN already used'
1463                s_logger.info('%s/%s entered used PIN %s' % (s_id,ref,pin_str))
1464                break
1465            if ok >= 1:
1466                #import pdb;pdb.set_trace()
1467                if self.isStudent():
1468                    if self.reference == "jamb_reg_no":
1469                        err = "You are already logged in."
1470                        s_logger.info('%s/%s checked admission with PIN %s though logged in' % (s_id,ref,pin_str))
1471                        break
1472                    if ok == 1:
1473                        s_logger.info('%s/%s successfully used PIN %s' % (s_id,ref,pin_str))
1474                    else:
1475                        s_logger.info('%s/%s repeatedly used PIN %s' % (s_id,ref,pin_str))
1476                    break
1477                else:
1478                    student = getStudentByRegNo(self,ref)
1479                    s_logger.info('%s/%s successfully used PIN %s' % (s_id,ref,pin_str))
1480                if student is None:
1481                    err = "Student record not found."
1482                    s_logger.info('%s not found in admission list' % (ref))
1483                    break
1484                s_id = student.getId()
1485                if ok == 2:
1486                    if self.reference == "jamb_reg_no":
1487                        if hasattr(self.portal_directories.students,s_id):
1488                            err = "Please login with your Student Id ${id} and 10-digit PIN."
1489                            mapping = {'id': s_id}
1490                            s_logger.info('%s/%s repeatedly checked admission with PIN %s' % (s_id,ref,pin_str))
1491                            break
1492                        else:
1493                            s_logger.info('%s/%s (non-member) repeatedly checked admission with PIN %s' % (s_id,ref,pin_str))
1494                    else:
1495                        err = "Unknown error"
1496                        s_logger.info('%s/%s repeatedly activated service with PIN %s' % (s_id,ref,pin_str))
1497                        break
1498                try:
1499                    student.getContent().makeStudentMember(s_id,password=pin[4:])
1500                    s_logger.info('%s/%s has been created using PIN %s' % (s_id,ref,pin_str))
1501                except:
1502                    err = "Please login with your Student Id ${id} and 10-digit PIN."
1503                    mapping = {'id': s_id}
1504                    s_logger.info('%s/%s could not be made a member with PIN %s' % (s_id,ref,pin_str))
1505                    break
1506            break
1507        if err:
1508            datastructure.setError(widget_id, err,mapping)
1509        else:
1510            datamodel = datastructure.getDataModel()
1511            datamodel[self.fields[0]] = ScratchCardPin(prefix,b,n)
1512            datastructure[widget_id] = ScratchCardPin(prefix,b,n)
1513            datastructure[widget_id+'_p'] = prefix
1514            datastructure[widget_id+'_b'] = b
1515            datastructure[widget_id+'_n'] = n
1516            datastructure['s_id'] = s_id
1517        return not err
1518
1519###)
1520
1521    def render(self, mode, datastructure, **kw): ###(
1522        """Render in mode from datastructure."""
1523        render_method = 'widget_scratch_card_pin_render'
1524        meth = getattr(self, render_method, None)
1525        if meth is None:
1526            raise RuntimeError("Unknown Render Method %s for widget type %s"
1527                               % (render_method, self.getId()))
1528
1529        # XXX AT: datastructure has to be set again here, in case we're in edit
1530        # or create mode, because a default value has to be provided.
1531        #import pdb;pdb.set_trace()
1532        datamodel = datastructure.getDataModel()
1533        v = datamodel[self.fields[0]]
1534        if v and type(v) is StringType:
1535            try:
1536                p,b,n = v.split('-')
1537                v = ScratchCardPin(p,b,n)
1538            except ValueError:
1539                v = ScratchCardPin(self.prefix,'XXX',v)
1540                pass
1541        if v:
1542            prefix= '%s' % v.p
1543            b = '%s' % v.b
1544            n = '%s' % v.n
1545        else:
1546            prefix= self.prefix
1547            if prefix.startswith('@'):
1548                prefix= getattr(self,self.prefix[1:])()
1549            b = n = ''
1550            v = ScratchCardPin(prefix,b,n)
1551        widget_id = self.getWidgetId()
1552        datastructure[widget_id] = v
1553        datastructure[widget_id+'_p'] = prefix
1554        datastructure[widget_id+'_b'] = b
1555        datastructure[widget_id+'_n'] = n
1556        return meth(mode=mode,
1557                    datastructure=datastructure,
1558                    )
1559    ###)
1560
1561InitializeClass(ScratchcardPinWidget)
1562widgetRegistry.register(ScratchcardPinWidget)
1563###)
1564
1565class PumePinWidget(ScratchcardPinWidget): ###(
1566    """ Pume Pin Widget"""
1567    meta_type = "Pume Pin Widget"
1568    catalog = "applicants_catalog"
1569    reference = ''
1570
1571    def prepare(self, datastructure, **kw): ###(
1572        """Prepare datastructure from datamodel."""
1573        datamodel = datastructure.getDataModel()
1574        #import pdb;pdb.set_trace()
1575        v = datamodel[self.fields[0]]
1576        widget_id = self.getWidgetId()
1577        if v and type(v) is StringType:
1578            try:
1579                p,b,n = v.split('-')
1580                v = ScratchCardPin(p,b,n)
1581            except ValueError:
1582                v = ScratchCardPin(v,'','')
1583        if v:
1584            p = '%s' % v.p
1585            b = '%s' % v.b
1586            n = '%s' % v.n
1587        else:
1588            p = self.prefix
1589            if p.startswith('@'):
1590                p = getattr(self,self.prefix[1:])()
1591            b = n = ''
1592            v = ScratchCardPin(p,b,n)
1593        datastructure[widget_id] = v
1594        datastructure[widget_id+'_p'] = p
1595        datastructure[widget_id+'_b'] = b
1596        datastructure[widget_id+'_n'] = n
1597    ###)
1598
1599    def validate(self, datastructure, **kw): ###(
1600        """Validate datastructure and update datamodel."""
1601        s_logger = logging.getLogger('Widgets.PumePinWidget.validate')
1602        widget_id = self.getWidgetId()
1603        v = datastructure[widget_id]
1604        err = 0
1605        mapping = {}
1606        prefix= self.prefix
1607        if prefix.startswith('@'):
1608            prefix= getattr(self,self.prefix[1:])()
1609        b = datastructure[widget_id+'_b'].strip()
1610        n = datastructure[widget_id+'_n'].strip()
1611        pins = self.portal_pins
1612        pin = "%(prefix)s%(b)s%(n)s" % vars()
1613        pin_str = "%(prefix)s-%(b)s-%(n)s" % vars()
1614        member_id = str(self.portal_membership.getAuthenticatedMember())
1615        do = 1
1616        expiration_date = self.REQUEST.get('expiration_date')
1617        if self.isStaff():
1618            do = 0
1619            err ='You are logged in, please log out. PIN neither checked nor used.'
1620            s_logger.info('%s tried to use scratch card %s' % (member_id,pin_str))
1621        elif self.isStudent():
1622            do = 0
1623            #ref = datastructure[self.reference]
1624            err ='You are logged in, please log out. PIN neither checked nor used.'
1625            s_logger.info('%s applied for screening test while logged in with pin %s' % (member_id,pin_str))
1626        elif len(b) > 1 and b.find('-') > -1:
1627            do = 0
1628            err = 'PIN must not contain "-"'
1629            s_logger.info('%s entered invalid PIN  containing "-"' % (member_id))
1630        elif n.find('-') > -1:
1631            do = 0
1632            err = 'PIN must not contain "-"'
1633            s_logger.info('%s entered invalid PIN  containing "-"' % (member_id))
1634        elif len(n) != 10:
1635            do = 0
1636            err = 'Invalid PIN length'
1637            s_logger.info('%s entered invalid PIN with length %d' % (member_id,len(n)))
1638        elif self.reference == "":
1639            ref = n
1640        else:
1641            ref = datastructure[self.reference]
1642            if datastructure.errors:
1643                do = 0
1644                datastructure.setError(widget_id, 'PIN neither checked nor used.')
1645                s_logger.info('%s/%s entered wrong data together with PIN %s' % (member_id,ref,pin_str))
1646        while do:
1647            if self.REQUEST.traverse_subpath:
1648                screening_type_request = self.REQUEST.traverse_subpath[0]
1649            else:
1650                screening_type_request = 'manage'
1651            if datastructure.has_key('record'):
1652                applicant = datastructure['record']
1653                if applicant.screening_type != screening_type_request and screening_type_request != 'manage':
1654                    err = "You are using the wrong access form!"
1655                    s_logger.info('%s tried to use %s application form but has applied for %s' % (ref,screening_type_request,applicant.screening_type))
1656                    break
1657            elif expiration_date and DateTime(expiration_date).lessThan(DateTime()):
1658                if not pins(student=ref):
1659                    if not self.applicants_catalog(reg_no=ref):
1660                        err = 'no application record found'
1661                        s_logger.info('%s/%s tried new application though expired with PIN %s' % (member_id,ref,pin_str))
1662                        break
1663                    else:
1664                        s_logger.info('%s/%s entered application record which has been created by import (with PIN %s)' % (member_id,ref,pin_str))
1665            ok,pin_record = pins.searchAndSetRecord(pin,ref,prefix)
1666            if ok < -2 or ok > 2:
1667                err = 'Unknown error, please report!'
1668                s_logger.info('%s/%s caused unknown error with PIN %s' % (member_id,ref,pin_str))
1669                break
1670            elif ok == -2:
1671                err = 'Service is already activated but with a different PIN.'
1672                s_logger.info('%s/%s repeatedly activated service but with different PIN %s' % (member_id,ref,pin_str))
1673                break
1674            elif ok == -1:
1675                err = 'Invalid PIN'
1676                s_logger.info('%s/%s entered invalid PIN %s' % (member_id,ref,pin_str))
1677                break
1678            if ok == 0:
1679                err = 'PIN already used'
1680                s_logger.info('%s/%s entered used PIN %s' % (member_id,ref,pin_str))
1681                break
1682            if ok >= 1:
1683                #screening_type = self.REQUEST.form.get('screening_type','unknown')
1684                #screening_type = datastructure['screening_type']
1685                if datastructure.has_key('record'):
1686                    applicant = datastructure['record']
1687                    if applicant.screening_type != screening_type_request\
1688                          and screening_type_request != 'manage':
1689                        err = "You are using the wrong access form!"
1690                        s_logger.info('%s tried to use %s application form but has applied for %s' % (ref,screening_type_request,applicant.screening_type))
1691                        break
1692                    if not applicant.pin:
1693                        s_logger.info('%s successfully used PIN %s' % (ref,pin_str))
1694                        d = {}
1695                        d['reg_no'] = applicant.reg_no
1696                        d['pin'] = pin_str
1697                        #d['screening_type'] = screening_type
1698                        #d['status'] = 'entered'
1699                        getattr(self,self.catalog).modifyRecord(**d)
1700                    elif applicant.pin != pin_str:
1701                        s_logger.info('%s/%s tried to enter application record with different PIN %s' % (member_id,ref,pin_str))
1702                    elif applicant.pin == pin_str:
1703                        s_logger.info('%s/%s repeatedly entered application record with PIN %s' % (member_id,ref,pin_str))
1704                else:
1705                    datastructure['reg_no'] = ref
1706                    res = self.applicants_catalog(reg_no = ref)
1707                    if res:
1708                        if getattr(res[0],'screening_type',None) != screening_type_request\
1709                              and screening_type_request != 'manage':
1710                            err = "You are using the wrong access form!"
1711                            s_logger.info('%s tried to use %s application form but has applied for %s' % (ref,screening_type_request,getattr(res[0],'screening_type',None)))
1712                            break
1713                        s_logger.info('%s/%s repeatedly entered application record with PIN %s' % (member_id,ref,pin_str))
1714                    else:
1715                        s_logger.info('%s successfully used PIN %s' % (ref,pin_str))
1716                        d = {}
1717                        d['reg_no'] = ref
1718                        d['pin'] = pin_str
1719                        d['status'] = 'entered'
1720                        d['screening_type'] = screening_type_request
1721                        d['serial'] = "%c%05d" % (pin_record.prefix_batch[-1],
1722                                                  pin_record.serial)
1723                        self.applicants_catalog.addRecord(**d)
1724
1725            break
1726        if err:
1727            datastructure.setError(widget_id, err,mapping)
1728        else:
1729            datamodel = datastructure.getDataModel()
1730            datamodel[self.fields[0]] = ScratchCardPin(prefix,b,n)
1731            datastructure[widget_id] = ScratchCardPin(prefix,b,n)
1732            datastructure[widget_id+'_p'] = prefix
1733            datastructure[widget_id+'_b'] = b
1734            datastructure[widget_id+'_n'] = n
1735        return not err
1736    ###)
1737
1738    def render(self, mode, datastructure, **kw): ###(
1739        """Render in mode from datastructure."""
1740        render_method = 'widget_scratch_card_pin_render'
1741        meth = getattr(self, render_method, None)
1742        if meth is None:
1743            raise RuntimeError("Unknown Render Method %s for widget type %s"
1744                               % (render_method, self.getId()))
1745
1746        # XXX AT: datastructure has to be set again here, in case we're in edit
1747        # or create mode, because a default value has to be provided.
1748        #import pdb;pdb.set_trace()
1749        datamodel = datastructure.getDataModel()
1750        v = datamodel[self.fields[0]]
1751        #import pdb;pdb.set_trace()
1752        if v and type(v) is StringType:
1753            try:
1754                p,b,n = v.split('-')
1755                v = ScratchCardPin(p,b,n)
1756            except ValueError:
1757                v = ScratchCardPin(self.prefix,'XXX',v)
1758                pass
1759        if v:
1760            prefix= '%s' % v.p
1761            b = '%s' % v.b
1762            n = '%s' % v.n
1763        else:
1764            prefix= self.prefix
1765            if prefix.startswith('@'):
1766                prefix= getattr(self,self.prefix[1:])()
1767            b = n = ''
1768            v = ScratchCardPin(prefix,b,n)
1769        widget_id = self.getWidgetId()
1770        datastructure[widget_id] = v
1771        datastructure[widget_id+'_p'] = prefix
1772        datastructure[widget_id+'_b'] = b
1773        datastructure[widget_id+'_n'] = n
1774        return meth(mode=mode,
1775                    datastructure=datastructure,
1776                    )
1777    ###)
1778
1779InitializeClass(PumePinWidget)
1780widgetRegistry.register(PumePinWidget)
1781###)
1782
1783class WAeUPImageWidget(CPSImageWidget): ###(
1784    """Photo widget."""
1785    meta_type = 'WAeUP Image Widget'
1786
1787    def render(self, mode, datastructure, **kw):
1788        render_method = 'widget_waeup_image_render'
1789        meth = getattr(self, render_method, None)
1790        if meth is None:
1791            raise RuntimeError("Unknown Render Method %s for widget type %s"
1792                               % (render_method, self.getId()))
1793        img_info = self.getImageInfo(datastructure)
1794        return meth(mode=mode, datastructure=datastructure, **img_info)
1795
1796InitializeClass(WAeUPImageWidget)
1797
1798widgetRegistry.register(WAeUPImageWidget)
1799###)
1800
1801class ApplicationImageWidget(CPSImageWidget): ###(
1802    """Image widget with filesystem storage."""
1803    meta_type = 'Application Image Widget'
1804    _properties = CPSImageWidget._properties +\
1805    (
1806     {'id': 'path', 'type': 'string', 'mode': 'w',
1807      'label': 'Relative Path'},
1808     {'id': 'id_field', 'type': 'string', 'mode': 'w',
1809      'label': 'Field to build the id'},
1810    )
1811    path = "images"
1812    storage_path = "%s/import/%s" % (i_home,path)
1813    id_field = "reg_no"
1814
1815    def getImageInfo(self, datastructure): ###(
1816        """Get the file info from the datastructure."""
1817        widget_id = self.getWidgetId()
1818        if  datastructure.has_key(widget_id):
1819            fileupload = datastructure[widget_id]
1820            dm = datastructure.getDataModel()
1821            field_id = self.fields[0]
1822            screening_type = datastructure.get('screening_type')
1823            current_filename = "%s_%s.jpg" % (datastructure[self.id_field],
1824                                            field_id,)
1825            base_path = os.path.join(screening_type,current_filename)
1826            content_url = os.path.join('viewimage_applicant',self.path,base_path)
1827            file_path = os.path.join(self.storage_path,base_path)
1828            #import pdb; pdb.set_trace()
1829        else:
1830            file_path = "XXX"
1831        # read the file from the filesystem
1832        if not os.path.exists(file_path):
1833            height = -1
1834            width = -1
1835            empty_file = True
1836            session_file = False
1837            current_filename = ''
1838            content_url = ''
1839            size = 0
1840            mimetype = ''
1841            last_modified = ''
1842            height = ''
1843            width = ''
1844
1845        else:
1846            image = open(file_path)
1847            from OFS.Image import getImageInfo as getImageInfoOFS
1848            image.seek(0)
1849            data = image.read(2000)
1850            size = len(data)
1851            empty_file = size == 0
1852            session_file = False
1853            last_modified = ''
1854            image.close()
1855            mimetype, width, height = getImageInfoOFS(data)
1856
1857            if width < 0:
1858                width = None
1859            if height < 0:
1860                height = None
1861
1862            if (self.allow_resize
1863                and height is not None
1864                and width  is not None):
1865                z_w = z_h = 1
1866                h = int(self.display_height)
1867                w = int(self.display_width)
1868                if w and h:
1869                    if w < width:
1870                        z_w = w / float(width)
1871                    if h < height:
1872                        z_h = h / float(height)
1873                    zoom = min(z_w, z_h)
1874                    width = int(zoom * width)
1875                    height = int(zoom * height)
1876                #import pdb;pdb.set_trace()
1877        image_info = {
1878            'empty_file': empty_file,
1879            'session_file': session_file,
1880            'current_filename': current_filename,
1881            'size': size,
1882            'last_modified': last_modified,
1883            'content_url': content_url,
1884            'mimetype': mimetype,
1885            }
1886        title = image_info['current_filename']
1887        alt = title or ''
1888        #height = int(self.display_height)
1889        #width = int(self.display_width)
1890        if height is None or width is None:
1891            tag = renderHtmlTag('img', src=image_info['content_url'],
1892                                alt=alt, title=title)
1893        else:
1894            tag = renderHtmlTag('img', src=image_info['content_url'],
1895                                width=str(width), height=str(height),
1896                                alt=alt, title=title)
1897
1898        image_info['height'] = height
1899        image_info['width'] = width
1900        image_info['image_tag'] = tag
1901        return image_info
1902    ###)
1903
1904    def checkFileName(self, filename, mimetype):
1905        return '', {}
1906        if mimetype and mimetype.startswith('image'):
1907            return '', {}
1908        return 'cpsschemas_err_image', {}
1909
1910    def prepare(self, datastructure, **kw): ###(
1911        """Prepare datastructure from datamodel."""
1912        datamodel = datastructure.getDataModel()
1913        widget_id = self.getWidgetId()
1914        file_name = datamodel[self.fields[0]]
1915        #import pdb; pdb.set_trace()
1916        if self.allow_resize:
1917            datastructure[self.getWidgetId() + '_resize'] = ''
1918        screening_type = datamodel.get('screening_type',None)
1919        if not screening_type:
1920            screening_type = self.REQUEST.form.get('screening_type','pume')
1921        datastructure["screening_type"] = screening_type
1922        datastructure[widget_id] = file_name
1923        datastructure[widget_id + '_choice'] = 'change'
1924        title = 'Passport Foto'
1925        datastructure[widget_id + '_filename'] = title
1926    ###)
1927
1928    def validate(self, datastructure, **kw): ###(
1929        """Update datamodel from user data in datastructure.
1930        """
1931        logger = logging.getLogger('Widgets.ApplicationImageWidget.validate')
1932        datamodel = datastructure.getDataModel()
1933        field_id = self.fields[0]
1934        widget_id = self.getWidgetId()
1935        store = False
1936        fileupload = None
1937        mimetype = None
1938        old_file = datamodel[field_id]
1939        # if old_file is not None:
1940        #     old_filename = old_file.title
1941        # else:
1942        #     old_filename = ''
1943        choice = datastructure[widget_id+'_choice']
1944        fileupload = datastructure[widget_id]
1945        is_upload = isinstance(fileupload, FileUpload)
1946        #import pdb; pdb.set_trace()
1947        if not is_upload and not datamodel[field_id]:
1948            if self.is_required:
1949                return self.validateError('Picture upload required', {},
1950                                          datastructure)
1951        if choice == 'delete':
1952            if self.is_required:
1953                return self.validateError('cpsschemas_err_required', {},
1954                                          datastructure)
1955            datamodel[field_id] = None
1956        elif choice == 'keep':
1957            fileupload = datastructure[widget_id]
1958            if isinstance(fileupload, PersistableFileUpload):
1959                # Keeping something from the session means we
1960                # actually want to store it.
1961                store = True
1962            # else:
1963            #     # Nothing to change, don't pollute datastructure
1964            #     # with something costly already stored, which therefore
1965            #     # doesn't need to be kept in the session.
1966            #     self.unprepare(datastructure)
1967        elif choice == 'change' and is_upload:
1968            if not fileupload:
1969                return self.validateError('cpsschemas_err_file_empty', {},
1970                                          datastructure)
1971            if not isinstance(fileupload, FileUpload):
1972                return self.validateError('cpsschemas_err_file', {},
1973                                          datastructure)
1974            fileupload.seek(0, 2) # end of file
1975            size = fileupload.tell()
1976            if not size:
1977                return self.validateError('cpsschemas_err_file_empty', {},
1978                                          datastructure)
1979            if self.size_max and size > self.size_max:
1980                max_size_str = self.getHumanReadableSize(self.size_max)
1981                err = 'This file is too big, the allowed max size is ${max_size}'
1982                logger.info('%s tried to upload picture with size %dk' %(datastructure['reg_no'],int(size)/1000) )
1983                err_mapping = {'max_size': max_size_str}
1984                return self.validateError(err, err_mapping, datastructure)
1985            store = True
1986
1987
1988        # Find filename
1989        if is_upload and store:
1990            ext ='jpg'
1991            screening_type = datastructure.get('screening_type')
1992            filename = "%s_%s.%s" % (datastructure[self.id_field],
1993                                     self.getWidgetId(),
1994                                     ext)
1995            datamodel[field_id] = filename
1996            registry = getToolByName(self, 'mimetypes_registry')
1997            mimetype = registry.lookupExtension(filename.lower())
1998            if mimetype is not None:
1999                mimetype = str(mimetype) # normalize
2000            file = self.makeFile(filename, fileupload, datastructure)
2001            # Fixup mimetype
2002            if mimetype and file.content_type != mimetype:
2003                file.content_type = mimetype
2004            # Store the file in the filesystem
2005            #import pdb;pdb.set_trace()
2006            base_path = os.path.join(self.storage_path, screening_type)
2007            if not os.path.exists(base_path):
2008                os.mkdir(base_path)
2009            full_path = os.path.join(base_path, filename)
2010            pict = open(full_path,"w")
2011            fileupload.seek(0)
2012            pict.write(fileupload.read())
2013            pict.close()
2014
2015
2016        return True
2017
2018###)
2019
2020    def render(self, mode, datastructure, **kw): ###(
2021        render_method = 'widget_passport_render'
2022        meth = getattr(self, render_method, None)
2023        if meth is None:
2024            raise RuntimeError("Unknown Render Method %s for widget type %s"
2025                               % (render_method, self.getId()))
2026        img_info = self.getImageInfo(datastructure)
2027        return meth(mode=mode, datastructure=datastructure, **img_info)
2028    ###)
2029
2030InitializeClass(ApplicationImageWidget)
2031
2032widgetRegistry.register(ApplicationImageWidget)
2033###)
2034
2035class FileImageWidget(CPSImageWidget): ###(
2036    """Image widget with filesystem storage."""
2037    meta_type = 'File Image Widget'
2038    _properties = CPSImageWidget._properties +\
2039    (
2040     {'id': 'path', 'type': 'string', 'mode': 'w',
2041      'label': 'Relative Path'},
2042     {'id': 'id_field', 'type': 'string', 'mode': 'w',
2043      'label': 'Field to build the id'},
2044     {'id': 'show_image', 'type': 'boolean', 'mode': 'w',
2045      'label': 'Show Image'},
2046    )
2047    path = "images"
2048    #storage_path = "%s/%s" % (i_home,path)
2049    id_field = ""
2050    show_image = False
2051
2052    def getStorageImageInfo(self,field_id):
2053        info = {}
2054        if self.id_field == "":
2055            student_id = self.getStudentId()
2056        else:
2057            student_id = datastructure[self.id_field]
2058        # student_path = os.path.join(self.storage_path,
2059        #                             student_id)
2060        student_path = getImagesDir(student_id)
2061        image_name = ''
2062        content_url = ''
2063        current_filename = ''
2064        if os.path.exists(student_path):
2065            for name in os.listdir(student_path):
2066                if name.startswith(field_id):
2067                    image_name = name
2068                    break
2069        if image_name:
2070            info['image_name'] = image_name
2071            info['content_url'] = os.path.join(self.portal_url(),
2072                                               "viewimage",
2073                                               student_id,
2074                                               image_name,
2075                                              )
2076            info['current_filename'] =  image_name
2077            info['file_path'] = os.path.join(student_path, image_name)
2078        return info
2079
2080    def getImageInfo(self, datastructure): ###(
2081        """Get the file info from the datastructure."""
2082        widget_id = self.getWidgetId()
2083        info = None
2084        if  datastructure.has_key(widget_id):
2085            fileupload = datastructure[widget_id]
2086            dm = datastructure.getDataModel()
2087            field_id = self.fields[0]
2088            info = self.getStorageImageInfo(field_id)
2089        else:
2090            file_path = "XXX"
2091            title = ""
2092        # read the file from the filesystem
2093        #import pdb; pdb.set_trace()
2094        #if not os.path.exists(file_path):
2095        if not info:
2096            title = ""
2097            height = -1
2098            width = -1
2099            empty_file = True
2100            session_file = False
2101            current_filename = ''
2102            content_url = ''
2103            size = 0
2104            mimetype = ''
2105            last_modified = ''
2106            height = ''
2107            width = ''
2108        else:
2109            title = info['image_name']
2110            current_filename = info['current_filename']
2111            content_url = info['content_url']
2112            image = open(info['file_path'])
2113            from OFS.Image import getImageInfo as getImageInfoOFS
2114            image.seek(0)
2115            data = image.read(2000)
2116            size = len(data)
2117            empty_file = size == 0
2118            session_file = False
2119            last_modified = ''
2120            image.close()
2121            mimetype, width, height = getImageInfoOFS(data)
2122            registry = getToolByName(self, 'mimetypes_registry')
2123            mimetype = (registry.lookupExtension(current_filename.lower()) or
2124                        registry.lookupExtension('file.bin'))
2125            if width < 0:
2126                width = None
2127            if height < 0:
2128                height = None
2129
2130            if (self.allow_resize
2131                and height is not None
2132                and width  is not None):
2133                z_w = z_h = 1
2134                h = int(self.display_height)
2135                w = int(self.display_width)
2136                if w and h:
2137                    if w < width:
2138                        z_w = w / float(width)
2139                    if h < height:
2140                        z_h = h / float(height)
2141                    zoom = min(z_w, z_h)
2142                    width = int(zoom * width)
2143                    height = int(zoom * height)
2144                #import pdb;pdb.set_trace()
2145        image_info = {
2146            'empty_file': empty_file,
2147            'session_file': session_file,
2148            'current_filename': title,
2149            'size': size,
2150            'last_modified': last_modified,
2151            'content_url': content_url,
2152            'mimetype': mimetype,
2153            }
2154        alt = title or ''
2155        #height = int(self.display_height)
2156        #width = int(self.display_width)
2157        if height is None or width is None:
2158            tag = renderHtmlTag('img', src=image_info['content_url'],
2159                                alt=alt, title=title)
2160        else:
2161            tag = renderHtmlTag('img', src=image_info['content_url'],
2162                                width=str(width), height=str(height),
2163                                alt=alt, title=title)
2164
2165        image_info['height'] = height
2166        image_info['width'] = width
2167        image_info['image_tag'] = tag
2168        image_info['show_image'] = self.show_image
2169        return image_info
2170    ###)
2171
2172    # def checkFileName(self, filename, mimetype):
2173    #     return '', {}
2174    #     if mimetype and mimetype.startswith('image'):
2175    #         return '', {}
2176    #     return 'cpsschemas_err_image', {}
2177
2178    def prepare(self, datastructure, **kw): ###(
2179        """Prepare datastructure from datamodel."""
2180        datamodel = datastructure.getDataModel()
2181        widget_id = self.getWidgetId()
2182        file_name = datamodel[self.fields[0]]
2183        if self.id_field == "":
2184            student_id = self.getStudentId()
2185        else:
2186            student_id = datastructure[self.id_field]
2187        if student_id is not None:
2188            # student_path = os.path.join(self.storage_path,
2189            #                             student_id)
2190            student_path = getImagesDir(student_id)
2191            if not os.path.exists(student_path):
2192                self.waeup_tool.moveImagesToFS(student_id)
2193        if self.allow_resize:
2194            datastructure[self.getWidgetId() + '_resize'] = ''
2195        datastructure[widget_id] = file_name
2196        datastructure[widget_id + '_choice'] = 'change'
2197        title = 'Passport Foto'
2198        datastructure[widget_id + '_filename'] = title
2199    ###)
2200
2201    def validate(self, datastructure, **kw): ###(
2202        """Update datamodel from user data in datastructure.
2203        """
2204        logger = logging.getLogger('Widgets.FileImageWidget.validate')
2205        datamodel = datastructure.getDataModel()
2206        field_id = self.fields[0]
2207        widget_id = self.getWidgetId()
2208        store = False
2209        fileupload = None
2210        mimetype = None
2211        old_file = datamodel[field_id]
2212        choice = datastructure[widget_id+'_choice']
2213        fileupload = datastructure[widget_id]
2214        is_upload = isinstance(fileupload, FileUpload)
2215        #import pdb; pdb.set_trace()
2216        if not is_upload and not datamodel[field_id]:
2217            if self.is_required:
2218                return self.validateError('Picture upload required', {},
2219                                          datastructure)
2220        if self.id_field == "":
2221            student_id = self.getStudentId()
2222        else:
2223            student_id = datastructure[self.id_field]
2224        if choice == 'delete':
2225            if self.is_required:
2226                return self.validateError('cpsschemas_err_required', {},
2227                                          datastructure)
2228            info= self.getStorageImageInfo(field_id)
2229            # Remove the file in the filesystem
2230            if info:
2231                os.remove(info['file_path'])
2232            datamodel[field_id] = None
2233        elif choice == 'keep':
2234            fileupload = datastructure[widget_id]
2235            if isinstance(fileupload, PersistableFileUpload):
2236                # Keeping something from the session means we
2237                # actually want to store it.
2238                store = True
2239            # else:
2240            #     # Nothing to change, don't pollute datastructure
2241            #     # with something costly already stored, which therefore
2242            #     # doesn't need to be kept in the session.
2243            #     self.unprepare(datastructure)
2244        elif choice == 'change' and is_upload:
2245            if not fileupload:
2246                return self.validateError('cpsschemas_err_file_empty', {},
2247                                          datastructure)
2248            if not isinstance(fileupload, FileUpload):
2249                return self.validateError('cpsschemas_err_file', {},
2250                                          datastructure)
2251            fileupload.seek(0, 2) # end of file
2252            size = fileupload.tell()
2253            if not size:
2254                return self.validateError('cpsschemas_err_file_empty', {},
2255                                          datastructure)
2256            if self.size_max and size > self.size_max:
2257                max_size_str = self.getHumanReadableSize(self.size_max)
2258                err = 'This file is too big, the allowed max size is ${max_size}'
2259                member_id = str(self.portal_membership.getAuthenticatedMember())
2260                logger.info('%s tried to upload picture with size %dk' %(member_id,int(size)/1000) )
2261                err_mapping = {'max_size': max_size_str}
2262                return self.validateError(err, err_mapping, datastructure)
2263            store = True
2264
2265
2266        # Find filename
2267        if is_upload and store:
2268            filename = cookId('', '', fileupload)[0].strip()
2269            base,ext = os.path.splitext(filename)
2270            filename = "%s_%s%s" % (field_id,
2271                                    student_id,
2272                                    ext)
2273            datamodel[field_id] = filename
2274            registry = getToolByName(self, 'mimetypes_registry')
2275            mimetype = registry.lookupExtension(filename.lower())
2276            if mimetype is not None:
2277                mimetype = str(mimetype) # normalize
2278            file = self.makeFile(filename, fileupload, datastructure)
2279            # Fixup mimetype
2280            if mimetype and file.content_type != mimetype:
2281                file.content_type = mimetype
2282            # Store the file in the filesystem
2283            #student_path = os.path.join(self.storage_path,student_id)
2284            student_path = getImagesDir(student_id)
2285            if not os.path.exists(student_path):
2286                os.mkdir(student_path)
2287            full_path = os.path.join(student_path, filename)
2288            pict = open(full_path,"w")
2289            #fileupload.seek(0)
2290            #import pdb; pdb.set_trace()
2291            pict.write(str(file.data))
2292            pict.close()
2293        return True
2294    ###)
2295
2296    def render(self, mode, datastructure, **kw): ###(
2297        render_method = 'widget_image_render'
2298        meth = getattr(self, render_method, None)
2299        #import pdb;pdb.set_trace()
2300        if meth is None:
2301            raise RuntimeError("Unknown Render Method %s for widget type %s"
2302                               % (render_method, self.getId()))
2303        img_info = self.getImageInfo(datastructure)
2304        return meth(mode=mode, datastructure=datastructure, **img_info)
2305    ###)
2306
2307InitializeClass(FileImageWidget)
2308
2309widgetRegistry.register(FileImageWidget)
2310###)
2311
2312class DiscFileWidget(CPSFileWidget): ###(
2313    """File widget with filesystem storage."""
2314    meta_type = 'Disc File Widget'
2315    _properties = CPSFileWidget._properties +\
2316    (
2317     {'id': 'path', 'type': 'string', 'mode': 'w',
2318      'label': 'Relative Path'},
2319    )
2320    path = "import"
2321    storage_path = "%s/%s" % (i_home,path)
2322
2323    def getStoredFileInfo(self,datastructure): ###(
2324        datamodel = datastructure.getDataModel()
2325        field_id = self.fields[0]
2326        widget_id = self.getWidgetId()
2327        file_name = datamodel[field_id]
2328        info = {}
2329        registry = getToolByName(self, 'mimetypes_registry')
2330        info['mimetype'] = registry.lookupExtension('file.csv')
2331        info['empty_file'] = True
2332        info['size'] = 0
2333        info['last_modified'] = ''
2334        file_path = os.path.join(self.storage_path, file_name)
2335        if os.path.exists(file_path):
2336            info['empty_file'] = False
2337            info['file_name'] = file_name
2338            info['content_url'] = os.path.join(self.portal_url(),
2339                                            "viewfile",
2340                                            file_name,
2341                                            )
2342            info['current_filename'] =  file_name
2343            # get the mimetype
2344            mimetype = (registry.lookupExtension(file_name.lower()) or
2345                        registry.lookupExtension('file.bin'))
2346            info['mimetype'] = mimetype
2347            info['file_path'] = file_path
2348        else:
2349            info['file_name'] = ''
2350            info['content_url'] = ''
2351            info['current_filename'] = ''
2352            info['file_path'] = ''
2353        return info
2354        ###)
2355
2356    def prepare(self, datastructure, **kw): ###(
2357        """Prepare datastructure from datamodel."""
2358        datamodel = datastructure.getDataModel()
2359        #import pdb;pdb.set_trace()
2360        widget_id = self.getWidgetId()
2361        file_name = datamodel[self.fields[0]]
2362        datastructure[widget_id] = file_name
2363        datastructure[widget_id + '_filename'] = file_name
2364        datastructure[widget_id+'_choice'] = "keep"
2365    ###)
2366
2367    def validate(self, datastructure, **kw): ###(
2368        """Update datamodel from user data in datastructure.
2369        """
2370        logger = logging.getLogger('Widgets.DiscFileWidget.validate')
2371        datamodel = datastructure.getDataModel()
2372        field_id = self.fields[0]
2373        widget_id = self.getWidgetId()
2374        store = False
2375        fileupload = None
2376        mimetype = None
2377        old_file = datamodel[field_id]
2378        choice = datastructure[widget_id+'_choice']
2379        fileupload = datastructure[widget_id]
2380        is_upload = isinstance(fileupload, FileUpload)
2381        if not is_upload and not datamodel[field_id]:
2382            if self.is_required:
2383                return self.validateError('File upload required', {},
2384                                          datastructure)
2385        if choice == 'delete':
2386            if self.is_required:
2387                return self.validateError('cpsschemas_err_required', {},
2388                                          datastructure)
2389            info = self.getStoredFileInfo(datastructure)
2390            # Remove the file in the filesystem
2391            if info:
2392                os.remove(info['file_path'])
2393            datamodel[field_id] = None
2394        elif choice == 'keep':
2395            fileupload = datastructure[widget_id]
2396            if isinstance(fileupload, PersistableFileUpload):
2397                # Keeping something from the session means we
2398                # actually want to store it.
2399                store = True
2400            # else:
2401            #     # Nothing to change, don't pollute datastructure
2402            #     # with something costly already stored, which therefore
2403            #     # doesn't need to be kept in the session.
2404            #     self.unprepare(datastructure)
2405        elif choice == 'change' and is_upload:
2406            if not fileupload:
2407                return self.validateError('cpsschemas_err_file_empty', {},
2408                                          datastructure)
2409            if not isinstance(fileupload, FileUpload):
2410                return self.validateError('cpsschemas_err_file', {},
2411                                          datastructure)
2412            fileupload.seek(0, 2) # end of file
2413            size = fileupload.tell()
2414            if not size:
2415                return self.validateError('cpsschemas_err_file_empty', {},
2416                                          datastructure)
2417            if self.size_max and size > self.size_max:
2418                max_size_str = self.getHumanReadableSize(self.size_max)
2419                err = 'This file is too big, the allowed max size is ${max_size}'
2420                member_id = str(self.portal_membership.getAuthenticatedMember())
2421                logger.info('%s tried to upload picture with size %dk' %(member_id,int(size)/1000) )
2422                err_mapping = {'max_size': max_size_str}
2423                return self.validateError(err, err_mapping, datastructure)
2424            store = True
2425
2426
2427        # Find filename
2428        if is_upload and store:
2429            filename = cookId('', '', fileupload)[0].strip()
2430            base,ext = os.path.splitext(filename)
2431            if ext not in ("csv",".csv"):
2432                return self.validateError('only csv files allowed', {},
2433                                          datastructure)
2434            uploads_folder = self.portal_url.getPortalObject().campus.uploads
2435            if hasattr(uploads_folder,filename):
2436                return self.validateError('upload object exists', {},
2437                                          datastructure)
2438            datamodel[field_id] = filename
2439            registry = getToolByName(self, 'mimetypes_registry')
2440            mimetype = registry.lookupExtension(filename.lower())
2441            if mimetype is not None:
2442                mimetype = str(mimetype) # normalize
2443            file = self.makeFile(filename, fileupload, datastructure)
2444            # Fixup mimetype
2445            if mimetype and file.content_type != mimetype:
2446                file.content_type = mimetype
2447            file_path = os.path.join(self.storage_path,filename)
2448            data = open(file_path,"w")
2449            data.write(str(file.data))
2450            data.close()
2451        return True
2452    ###)
2453
2454    def render(self, mode, datastructure, **kw): ###(
2455        render_method = 'widget_uploadfile_render'
2456        meth = getattr(self, render_method, None)
2457        #import pdb;pdb.set_trace()
2458        if meth is None:
2459            raise RuntimeError("Unknown Render Method %s for widget type %s"
2460                               % (render_method, self.getId()))
2461        file_info = self.getStoredFileInfo(datastructure)
2462
2463        return meth(mode=mode, datastructure=datastructure, **file_info)
2464    ###)
2465
2466InitializeClass(DiscFileWidget)
2467
2468widgetRegistry.register(DiscFileWidget)
2469###)
2470
2471###########
2472
Note: See TracBrowser for help on using the repository browser.