source: WAeUP_SRP/trunk/Widgets.py @ 3885

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

implement password notification module (send mail not yet tested)

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