source: WAeUP_SRP/base/Widgets.py @ 3682

Last change on this file since 3682 was 3494, checked in by joachim, 17 years ago

implement certificates_catalog

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