source: ZMS/trunk/_objattrs.py @ 1874

Revision 1874, 59.0 KB checked in by zmsdev, 2 weeks ago (diff)

added support for repetitive meta-objects

Line 
1################################################################################
2# _objattrs.py
3#
4# This program is free software; you can redistribute it and/or
5# modify it under the terms of the GNU General Public License
6# as published by the Free Software Foundation; either version 2
7# of the License, or (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program; if not, write to the Free Software
16# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17################################################################################
18
19# Imports.
20from DateTime.DateTime import DateTime
21from types import StringTypes
22import ZPublisher.HTTPRequest
23import datetime
24import string
25import time
26import urllib
27import zExceptions
28# Product Imports.
29import _blobfields
30import _globals
31import ZMSMetaobjManager
32
33
34# ------------------------------------------------------------------------------
35#  _objattrs.utf8:
36# ------------------------------------------------------------------------------
37def utf8(v, encoding = 'latin-1'):
38  if type( v) in StringTypes:
39    cp1252_map = {
40      "\x80" : "\xe2\x82\xac", # /* EURO SIGN */
41      "\x82" : "\xe2\x80\x9a", # /* SINGLE LOW-9 QUOTATION MARK */
42      "\x83" : "\xc6\x92",    # /* LATIN SMALL LETTER F WITH HOOK */
43      "\x84" : "\xe2\x80\x9e", # /* DOUBLE LOW-9 QUOTATION MARK */
44      "\x85" : "\xe2\x80\xa6", # /* HORIZONTAL ELLIPSIS */
45      "\x86" : "\xe2\x80\xa0", # /* DAGGER */
46      "\x87" : "\xe2\x80\xa1", # /* DOUBLE DAGGER */
47      "\x88" : "\xcb\x86",    # /* MODIFIER LETTER CIRCUMFLEX ACCENT */
48      "\x89" : "\xe2\x80\xb0", # /* PER MILLE SIGN */
49      "\x8a" : "\xc5\xa0",    # /* LATIN CAPITAL LETTER S WITH CARON */
50      "\x8b" : "\xe2\x80\xb9", # /* SINGLE LEFT-POINTING ANGLE QUOTATION */
51      "\x8c" : "\xc5\x92",    # /* LATIN CAPITAL LIGATURE OE */
52      "\x8e" : "\xc5\xbd",    # /* LATIN CAPITAL LETTER Z WITH CARON */
53      "\x91" : "\xe2\x80\x98", # /* LEFT SINGLE QUOTATION MARK */
54      "\x92" : "\xe2\x80\x99", # /* RIGHT SINGLE QUOTATION MARK */
55      "\x93" : "\xe2\x80\x9c", # /* LEFT DOUBLE QUOTATION MARK */
56      "\x94" : "\xe2\x80\x9d", # /* RIGHT DOUBLE QUOTATION MARK */
57      "\x95" : "\xe2\x80\xa2", # /* BULLET */
58      "\x96" : "\xe2\x80\x93", # /* EN DASH */
59      "\x97" : "\xe2\x80\x94", # /* EM DASH */
60      "\x98" : "\xcb\x9c",    # /* SMALL TILDE */
61      "\x99" : "\xe2\x84\xa2", # /* TRADE MARK SIGN */
62      "\x9a" : "\xc5\xa1",    # /* LATIN SMALL LETTER S WITH CARON */
63      "\x9b" : "\xe2\x80\xba", # /* SINGLE RIGHT-POINTING ANGLE QUOTATION*/
64      "\x9c" : "\xc5\x93",    # /* LATIN SMALL LIGATURE OE */
65      "\x9e" : "\xc5\xbe",    # /* LATIN SMALL LETTER Z WITH CARON */
66      "\x9f" : "\xc5\xb8"      # /* LATIN CAPITAL LETTER Y WITH DIAERESIS*/
67    }
68    if encoding == 'latin-1':
69      n = ''
70      for i in v:
71        if i in cp1252_map.keys():
72          c = '&#%i;'%ord( i)
73          n += c
74        else:
75          n += i
76      v = n
77    v = unicode( v, encoding).encode( 'utf-8')
78    if encoding == 'latin-1':
79      for i in cp1252_map.keys():
80        c = '&#%i;'%ord( i)
81        j = 0
82        while j >= 0:
83          j = v.find( c)
84          if j >= 0:
85            v = v[:j] + cp1252_map[ i] + v[j+len(c):]
86    return v
87  elif type( v) is list:
88    return map(lambda x: utf8( x, encoding), v)
89  elif type( v) is tuple:
90    return tuple(map(lambda x: utf8( x, encoding), list(v)))
91  elif type( v) is dict:
92    keys = v.keys()
93    vals = map(lambda x: utf8(v[x],encoding), keys)
94    return _globals.map_key_vals(keys, vals)
95  else:
96    return v
97
98
99# ------------------------------------------------------------------------------
100#  _objattrs.setutf8attr:
101# ------------------------------------------------------------------------------
102def setutf8attr(self, obj_vers, obj_attr, langId):
103  charset = self.getLang(langId).get('charset','')
104  if len(charset) == 0:
105    charset = 'latin-1'
106  key = self.getObjAttrName(obj_attr,langId)
107  v = getattr(obj_vers,key,None)
108  v = utf8(v,charset)
109  setattr(obj_vers,key,v)
110
111
112# ------------------------------------------------------------------------------
113#  _objattrs.getobjattr:
114# ------------------------------------------------------------------------------
115def getobjattr(self, obj, obj_attr, lang):
116  key = self.getObjAttrName(obj_attr,lang)
117  v = None
118  if key in obj.__dict__.keys():
119    v = getattr(obj,key)
120  # Default value.
121  if v is None:
122    datatype = obj_attr['datatype_key']
123    default = obj_attr.get('default',_globals.dtMapping[datatype][1])
124    # Default inactive in untranslated languages.
125    if obj_attr['id'] == 'active' and len(self.getLangIds()) > 1 and not self.isTranslated(lang,self.REQUEST):
126        default = 0
127    if default is not None:
128      if datatype in _globals.DT_DATETIMES and default == '{now}':
129        default = time.time()
130      elif type(default) is list or type(default) is tuple:
131        v = self.copy_list(default)
132      elif type(default) is dict:
133        v = default.copy()
134      else:
135        if type( default) is str and len( default) > 0:
136          default = _globals.dt_html( self, str( default), self.REQUEST)
137        v = default
138  return v
139
140# ------------------------------------------------------------------------------
141#  _objattrs.setobjattr:
142# ------------------------------------------------------------------------------
143def setobjattr(self, obj, obj_attr, value, lang):
144  key = self.getObjAttrName(obj_attr,lang)
145  # Assign value.
146  setattr(obj,key,value)
147
148# ------------------------------------------------------------------------------
149#  _objattrs.cloneobjattr:
150# ------------------------------------------------------------------------------
151def cloneobjattr(self, src, dst, obj_attr, lang):
152  _globals.writeLog( self, "[cloneobjattr]: Clone object-attributes from '%s' to '%s'"%(str(src),str(dst)))
153  # Fetch value.
154  v = getobjattr(self,src,obj_attr,lang)
155  # Clone value.
156  if v is not None:
157    datatype = obj_attr['datatype_key']
158    if datatype in _globals.DT_BLOBS:
159      try:
160        v = v._getCopy()
161      except:
162        e = "[cloneobjattr]: Can't clone object-attribute: obj_attr=%s, lang=%s, v=%s!"%(str(obj_attr), str(lang), str(v))
163        _globals.writeError( self, e)
164        raise zExceptions.InternalError(e)
165    elif type(v) is list or type(v) is tuple:
166      v = self.copy_list(v)
167    elif type(v) is dict:
168      v = v.copy()
169  # Assign value.
170  setobjattr(self,dst,obj_attr,v,lang)
171
172
173################################################################################
174################################################################################
175###
176###   Object Attributes
177###
178################################################################################
179################################################################################
180class ObjAttrs:
181
182    # --------------------------------------------------------------------------
183    #  ObjAttrs.ajaxGetObjOptions:
184    # --------------------------------------------------------------------------
185    def ajaxGetObjOptions(self, key, meta_id, fmt=None, REQUEST=None):
186      """ ObjAttrs.ajaxGetObjOptions """
187      RESPONSE = REQUEST.RESPONSE
188      content_type = 'text/plain; charset=utf-8'
189      filename = 'ajaxGetObjOptions.txt'
190      RESPONSE.setHeader('Content-Type',content_type)
191      RESPONSE.setHeader('Content-Disposition','inline;filename="%s"'%filename)
192      RESPONSE.setHeader('Cache-Control', 'no-cache')
193      RESPONSE.setHeader('Pragma', 'no-cache')
194      obj_attr = self.getObjAttr( key, meta_id)
195      l = map( lambda x: x[1], self.getObjOptions( obj_attr, REQUEST))
196      q = REQUEST.get( 'q', '').upper()
197      if q:
198        l = filter( lambda x: x.upper().find( q) >= 0, l)
199      limit = int(REQUEST.get('limit',self.getConfProperty('ZMS.input.autocomplete.limit',15)))
200      if len(l) > limit:
201        l = l[:limit]
202      if fmt == 'json':
203        return self.str_json(l)
204      return '\n'.join(l)
205
206
207    # --------------------------------------------------------------------------
208    #  ObjAttrs.ajaxGetObjAttrs:
209    # --------------------------------------------------------------------------
210    def ajaxGetObjAttrs(self, meta_id, REQUEST):
211      """ ObjAttrs.ajaxGetObjAttrs """
212      RESPONSE = REQUEST.RESPONSE
213      content_type = 'text/xml; charset=utf-8'
214      filename = 'ajaxGetObjAttrs.xml'
215      RESPONSE.setHeader('Content-Type',content_type)
216      RESPONSE.setHeader('Content-Disposition','inline;filename="%s"'%filename)
217      RESPONSE.setHeader('Cache-Control', 'no-cache')
218      RESPONSE.setHeader('Pragma', 'no-cache')
219      return self.getXmlHeader() + self.toXmlString( self.getObjAttrs( meta_id))
220
221
222    # --------------------------------------------------------------------------
223    #  ObjAttrs.getObjAttrs:
224    #
225    #  Returns object-attributes and resolves meta-dictionaries.
226    # --------------------------------------------------------------------------
227    def getObjAttrs(self, meta_id=None):
228      meta_id = _globals.nvl( meta_id, self.meta_id)
229      obj_attrs = getattr( self, 'dObjAttrs', {})
230      return obj_attrs.get(meta_id,{})
231
232
233    # --------------------------------------------------------------------------
234    #  ObjAttrs.getObjAttr:
235    # --------------------------------------------------------------------------
236    def getObjAttr(self, key, meta_id=None):
237      obj_attrs = self.getObjAttrs( meta_id)
238      return obj_attrs.get(key,{'id':key,'key':key,'xml':False,'multilang':False,'lang_inherit':False,'name':'UNKNOWN','datatype':'string','datatype_key':_globals.DT_UNKNOWN})
239
240
241    # --------------------------------------------------------------------------
242    #  ObjAttrs.getObjAttrLabel:
243    # --------------------------------------------------------------------------
244    def getObjAttrLabel(self, obj_attr):
245      lang = self.REQUEST['lang']
246      for key in [ 'name', 'id']:
247        if obj_attr.has_key( key):
248          name = obj_attr.get( key)
249          lang_key = name
250          lang_str = self.getLangStr( lang_key, lang)
251          if lang_key != lang_str:
252            return lang_str
253          lang_key = name.upper()
254          lang_str = self.getLangStr( lang_key, lang)
255          if lang_key != lang_str:
256            return lang_str
257          lang_key = ('attr_'+name).upper()
258          lang_str = self.getLangStr( lang_key, lang)
259          if lang_key != lang_str:
260            return lang_str
261      return obj_attr.get('name',obj_attr['id'].capitalize())
262
263
264    # --------------------------------------------------------------------------
265    #  ObjAttrs.getObjOptions:
266    # --------------------------------------------------------------------------
267    def getObjOptions(self, obj_attr, REQUEST):
268      optpl = []
269      if obj_attr.has_key('options'):
270        opts = []
271        obj_attropts = obj_attr['options']
272        if type(obj_attropts) is list:
273          dtml = ''.join(map(lambda x: str(obj_attropts[x*2]),range(len(obj_attropts)/2)))
274          if len(obj_attropts)==2 and self.getLinkObj(obj_attropts[0],REQUEST):
275            ob = self.getLinkObj(obj_attropts[0],REQUEST)
276            metaObj = self.getMetaobj(ob.meta_id)
277            res = ob.getObjProperty(metaObj['attrs'][0]['id'],REQUEST)
278            res = map(lambda x: {'key':x['key'],'value':x.get('value',x.get('value_%s'%REQUEST['lang']))},res)
279            res = self.sort_list(res,'value','asc')
280            opts = map(lambda x: [x['key'],x['value']],res)
281          elif dtml.find('<dtml')>=0:
282            try:
283              opts = _globals.dt_html(self,dtml,REQUEST)
284            except:
285              opts = _globals.writeError(self,'[getObjOptions]: key=%s'%obj_attr['id'])
286          else:
287            for i in range(len(obj_attropts)/2):
288              opts.append([obj_attropts[i*2],obj_attropts[i*2+1]])
289        elif type(obj_attropts) is dict:
290          for k in obj_attropts.keys():
291            opts.append([k,obj_attropts[k]])
292        for opt in opts:
293          lang_attr = 'OPT_'
294          for skey in obj_attr['id'].split('_'):
295            lang_attr += skey[0]
296          lang_attr += '_' + str(opt[1]).replace(' ','')
297          lang_attr = lang_attr.upper()
298          lang_str = self.getZMILangStr(lang_attr)
299          value = str(opt[0])
300          display = str(opt[1])
301          if lang_attr != lang_str:
302            display = lang_str
303          optpl.append([value,display])
304      return optpl
305
306    # --------------------------------------------------------------------------
307    #  ObjAttrs.getObjAttrName:
308    # --------------------------------------------------------------------------
309    def getObjAttrName(self, obj_attr, lang=None):
310      attr = obj_attr['id']
311      if obj_attr['multilang']:
312        if lang is None:
313          lang = self.getPrimaryLanguage()
314        attr = '%s_%s'%(attr,lang)
315      return attr
316
317    # --------------------------------------------------------------------------
318    #  ObjAttrs.isDisabledAttr:
319    # --------------------------------------------------------------------------
320    def isDisabledAttr(self, obj_attr, REQUEST):
321      lang = REQUEST.get('lang',self.getPrimaryLanguage())
322      return REQUEST.get(obj_attr['id']+'-disabled',False) or not (obj_attr['multilang'] or REQUEST.get('ZMS_INSERT',None) is not None or self.getDCCoverage(REQUEST).find('.'+lang)>0)
323
324
325    ############################################################################
326    #
327    #  INPUT-FIELDS
328    #
329    ############################################################################
330
331    # --------------------------------------------------------------------------
332    #  ObjAttrs.getObjAttrInput:
333    # --------------------------------------------------------------------------
334    def getObjAttrInput(self, fmName, obj_attr, value, REQUEST):
335   
336      #-- DATATYPE
337      datatype = obj_attr['datatype_key']
338     
339      #-- NAME
340      lang = REQUEST['lang']
341      attr = self.getObjAttrName(obj_attr,lang)
342      elName = self.REQUEST.get('objAttrNamePrefix','') + attr
343     
344      #-- INPUTTYPE
345      inputtype = obj_attr.get('type','string')
346     
347      #-- ENABLED / DISABLED
348      enabled = not self.isDisabledAttr(obj_attr,REQUEST)
349      disabled = obj_attr['id'].find('_')==0
350     
351      #-- Meta-Object
352      meta_id = REQUEST.get( 'ZMS_INSERT', self.meta_id)
353      metaObj = self.getMetaobj( meta_id)
354     
355      #-- Label
356      lang_str = self.getObjAttrLabel(obj_attr)
357     
358      #-- Mandatory
359      mandatory = obj_attr.get('mandatory',0)
360     
361      #-- Repetitive-Fields.
362      if obj_attr.get('repetitive',0):
363        return self.f_selectRepetitive(self,ob=self,fmName=fmName,elName=elName,value=value,obj_attr=obj_attr,REQUEST=REQUEST)
364     
365      #-- ID-Fields.
366      if inputtype == 'identifier':
367        if value == '': value = 'e%i'%self.getSequence().nextVal()
368        return '<div class="form-element"><code><input type="hidden" name="%s" value="%s">%s</code></div>'%(elName,value,value)
369     
370      #-- Richtext-Fields.
371      elif inputtype == 'richtext':
372        REQUEST.set('data',value)
373        form_fixed = False
374        css = 'form-element'
375        wrap = 'virtual'
376        filteredMetaObjAttrs = filter( lambda x: x['id']=='format', metaObj['attrs'])
377        if len(filteredMetaObjAttrs) == 1:
378          if REQUEST.get('ZMS_INSERT'):
379            default = _globals.dt_html( self, str( filteredMetaObjAttrs[0].get('default','')), REQUEST)
380            if default:
381              fmt = default
382            else:
383              fmt = self.getTextFormatDefault()
384            data = ''
385          else:
386            fmt = self.getObjProperty('format',REQUEST)
387            txt = self.getObjProperty('text',REQUEST)
388            data = self.renderText(None,'text',txt,REQUEST)
389          REQUEST.set('format',fmt)
390          REQUEST.set('data',data)
391          text_fmt = self.getTextFormat(fmt,REQUEST)
392          form_fixed = form_fixed or ( text_fmt is not None and not text_fmt.getTag() and not text_fmt.getSubTag())
393        ltxt = str(value).lower()
394        form_fixed = form_fixed or ( ltxt.find( '<form') >= 0 or ltxt.find( '<input') >= 0 or ltxt.find( '<script') >= 0)
395        if form_fixed:
396          css = 'form-fixed'
397          wrap = 'off'
398        if disabled:
399          css += '-disabled'
400        return self.f_selectRichtext(self,ob=self,fmName=fmName,elName=elName,cols=50,rows=15,value=value,key=obj_attr['id'],metaObj=metaObj,enabled=enabled,lang=lang,lang_str=lang_str,REQUEST=REQUEST,css=css,wrap=wrap)
401     
402      #-- Color-Fields.
403      elif inputtype == 'color':
404        return self.f_selectColor(self,ob=self,fmName=fmName,elName=elName,value=value,key=obj_attr['id'],lang_str=lang_str,mandatory=mandatory,REQUEST=REQUEST)
405     
406      #-- Image-Fields.
407      elif inputtype == 'image':
408        return self.f_selectImage(self,ob=self,fmName=fmName,elName=elName,value=value,key=obj_attr['id'],metaObj=metaObj,lang=lang,REQUEST=REQUEST)
409     
410      #-- File-Fields.
411      elif inputtype == 'file':
412        return self.f_selectFile(self,ob=self,fmName=fmName,elName=elName,value=value,key=obj_attr['id'],metaObj=metaObj,lang=lang,REQUEST=REQUEST)
413     
414      #-- Password-Fields.
415      if inputtype == 'password':
416        return self.getPasswordInput(fmName=fmName,elName=elName,value=value)
417     
418      #-- Dictionary/List-Fields.
419      elif inputtype in [ 'dictionary', 'list']:
420        css = 'form-fixed'
421        wrap = 'virtual'
422        if disabled:
423          css += '-disabled'
424        cols = 35
425        rows = 1
426        inp = []
427        inp.append(self.getTextArea(fmName,elName,cols,rows,self.toXmlString(value),enabled,REQUEST,css,wrap))
428        return ''.join(inp)
429     
430      #-- Text-Fields.
431      elif inputtype in [ 'text', 'xml']:
432        css = 'form-element'
433        wrap = 'virtual'
434        if inputtype in ['xml']:
435          css = 'form-fixed'
436          wrap = 'off'
437        if disabled:
438          css += '-disabled'
439        cols = None
440        rows = 5
441        extra = ' onselect="storeCaret(this)"'
442        return self.getTextArea(fmName,elName,cols,rows,value,enabled,REQUEST,css,wrap,extra)
443     
444      #-- Boolean-Fields.
445      elif inputtype == 'boolean':
446        return self.getCheckbox(fmName=fmName,elName=elName,elId=obj_attr['id'],value=value,enabled=enabled,hidden=False,REQUEST=REQUEST)
447     
448      #-- Autocomplete-Fields.
449      elif inputtype in ['autocomplete','multiautocomplete']:
450        css = 'form-element'
451        if disabled: css += '-disabled'
452        return self.f_selectAutocomplete(self,fmName=fmName,elName=elName,value=value,type=inputtype,key=obj_attr['id'],lang_str=lang_str,enabled=enabled,css=css,REQUEST=REQUEST)
453     
454      #-- Select-Fields.
455      elif inputtype in ['multiselect','select']:
456        css = 'form-element'
457        if disabled: css += '-disabled'
458        optpl = self.getObjOptions(obj_attr,REQUEST)
459        return self.getSelect(fmName,elName,value,inputtype,lang_str,mandatory,optpl,enabled,REQUEST,css)
460     
461      #-- Input-Fields.
462      else:
463        css = 'form-element'
464        if disabled: css += '-disabled'
465        if datatype in _globals.DT_DATETIMES:
466          size = 12
467          fmt_str = 'DATETIME_FMT'
468          if datatype == _globals.DT_DATE:
469            size = 8
470            fmt_str = 'DATE_FMT'
471          elif datatype == _globals.DT_TIME:
472            size = 8
473            fmt_str = 'TIME_FMT'
474          return self.getDateTimeInput(fmName,elName,size,value,enabled,fmt_str,REQUEST,css)
475        elif datatype == _globals.DT_URL:
476          size = 22
477          elTextName = ''
478          return self.getUrlInput( fmName, elName, elTextName, size, value, enabled, REQUEST, css )
479        else:
480          size = None
481          extra = ''
482          if obj_attr.has_key('size'):
483            size = obj_attr['size']
484          elif datatype in [_globals.DT_INT]:
485            size = 5
486          elif datatype in [_globals.DT_FLOAT]:
487            size = 8
488          elif datatype in [_globals.DT_AMOUNT]:
489            size = 8
490            extra = 'style="text-align: right;"'
491            if value is not None:
492              try:
493                value = '%1.2f'%float(value)
494              except:
495                pass
496          inp = []
497          inp.append(self.getTextInput( fmName, elName, size, value, 'text', enabled, REQUEST, css, extra ))
498          if datatype in [_globals.DT_AMOUNT]:
499            inp.append('&nbsp;'+self.getConfProperty('ZMS.locale.amount.unit','EUR'))
500          return ''.join(inp)
501
502    # --------------------------------------------------------------------------
503    #  ObjAttrs.getObjInput:
504    # --------------------------------------------------------------------------
505    def getObjInput(self, key, REQUEST):
506      id = self.id
507      fmName = REQUEST.get( 'fmName' ,'form0_%s'%id)
508      meta_id = REQUEST.get( 'ZMS_INSERT', None)
509      obj_attr = self.getObjAttr( key, _globals.nvl( meta_id, self.meta_id))
510      if meta_id is None:
511        value = self.getObjAttrValue( obj_attr, REQUEST)
512      else:
513        default = ''
514        datatype = obj_attr['datatype_key']
515        if datatype == _globals.DT_BOOLEAN:
516          default = 0
517        value = REQUEST.get( '%s_value'%key, obj_attr.get( 'default', default))
518      return self.getObjAttrInput( fmName, obj_attr, value, REQUEST)
519
520
521    # --------------------------------------------------------------------------
522    #  ObjAttrs.hasObjProperty:
523    #
524    #  Checks if object has specified property.
525    # --------------------------------------------------------------------------
526    def hasObjProperty(self, key, REQUEST):
527
528      #-- REQUEST
529      lang = REQUEST.get('lang',self.getPrimaryLanguage())
530     
531      #-- DEFINITION
532      obj_attr = self.getObjAttr(key)
533     
534      #-- OBJECT (Live / Work).
535      ob = self.getObjVersion(REQUEST)
536     
537      #-- ATTR
538      attr = self.getObjAttrName(obj_attr,lang)
539     
540      #-- Return true if object has specified property, false else.
541      return ob.__dict__.get(attr,None) is not None
542
543
544    """
545    ############################################################################
546    #
547    #  Get
548    #
549    ############################################################################
550    """
551
552    # --------------------------------------------------------------------------
553    #  ObjAttrs._getObjAttrValue:
554    # --------------------------------------------------------------------------
555    def _getObjAttrValue(self, obj_attr, obj_vers, lang):
556     
557      datatype = obj_attr['datatype_key']
558      set, value = False, getobjattr(self,obj_vers,obj_attr,lang)
559     
560      obj_default = _globals.dtMapping[datatype][1]
561     
562      #-- Blob-Fields
563      if datatype in _globals.DT_BLOBS:
564        if type(value) in StringTypes:
565          set, value = True, None
566        elif value is not None:
567          value = value._createCopy( self, obj_attr['id'])
568          value.lang = lang
569     
570      #-- DateTime-Fields.
571      elif datatype in _globals.DT_DATETIMES:
572        if value is not None:
573          if type(value) in StringTypes:
574            fmt_str = 'DATETIME_FMT'
575            if datatype == _globals.DT_DATE:
576              fmt_str = 'DATE_FMT'
577            elif datatype == _globals.DT_TIME:
578              fmt_str = 'TIME_FMT'
579            _globals.writeLog( self, "[_getObjAttrValue]: type(value) is type(string) - parseLangFmtDate(%s)"%(str(value)))
580            set, value = True, self.parseLangFmtDate(value)
581          elif type(value) is not time.struct_time:
582            _globals.writeLog( self, "[_getObjAttrValue]: type(value) is not time.struct_time - getDateTime(%s)"%(str(value)))
583            set, value = True, _globals.getDateTime(value)
584     
585      #-- List-Fields.
586      elif datatype == _globals.DT_LIST:
587        if not type(value) is type(obj_default):
588          set, value = True, [value]
589     
590      #-- Integer-Fields.
591      elif datatype in _globals.DT_INTS and not type(value) is type(obj_default):
592        try:
593          set, value = type( value) is not int, int(value)
594        except:
595          value = obj_default
596     
597      #-- Float-Fields.
598      elif datatype == _globals.DT_FLOAT and not type(value) is type(obj_default):
599        try:
600          set, value = type( value) is not float, float( value)
601        except:
602          value = obj_default
603     
604      #-- Url-Fields
605      elif datatype == _globals.DT_URL and value.startswith('{$') and not value.startswith('{$__') and self.getConfProperty('ZMS.InternalLinks.autocorrection',0)==1:
606        try:
607          old = value
608          value = self.validateLinkObj(value)
609          set = old != value
610        except:
611          _globals.writeError(self,'[_getObjAttrValue]: Unexpected Exception when processing Url-Fields: value=%s!'%str(value))
612     
613      #-- SET?
614      if set:
615        attr = self.getObjAttrName( obj_attr, lang)
616        _globals.writeLog( self, "[_getObjAttrValue]: setattr(%s,%s)"%(attr,str(value)))
617        setattr(obj_vers,attr,value)
618     
619      # Return value.
620      return value
621
622
623    # --------------------------------------------------------------------------
624    #  ObjAttrs.getObjAttrValue:
625    # --------------------------------------------------------------------------
626    def getObjAttrValue(self, obj_attr, REQUEST):
627      datatype = obj_attr['datatype_key']
628      obj_vers = self.getObjVersion(REQUEST)
629      lang = REQUEST.get('lang',self.getPrimaryLanguage())
630      while True:
631        value = self._getObjAttrValue(obj_attr,obj_vers,lang)
632        empty = False
633        if obj_attr['multilang'] and \
634           obj_attr['lang_inherit']:
635          lang = self.getParentLanguage(lang)
636          if lang is not None:
637            empty = empty or (value is None)
638            empty = empty or (datatype in _globals.DT_NUMBERS and value==0)
639            empty = empty or (datatype in _globals.DT_STRINGS and value=='')
640            empty = empty or (datatype == _globals.DT_LIST and value==[])
641        if not empty: break
642      return value
643
644
645    # --------------------------------------------------------------------------
646    #  ObjAttrs.getObjProperty:
647    #
648    #  Retrieves value for specified property.
649    #
650    #  @deprecated: use attr(key) instead!
651    # --------------------------------------------------------------------------
652    def getObjProperty(self, key, REQUEST={}, par=None):
653     
654      #-- [ReqBuff]: Fetch buffered value from Http-Request.
655      reqBuffId = '%s_%s'%('getObjProperty',key)
656      try:
657        if ( type( par) is dict and par.get( 'fetchReqBuff') in [ 0, False]) or \
658           ( REQUEST.get( 'ZMS_VERSION_%s'%self.id) is not None):
659          raise zExceptions.InternalError('ReqBuff set inactive!')
660        forced = type( par) is dict and par.get( 'fetchReqBuff') in [ 1, True]
661        value = self.fetchReqBuff( reqBuffId, REQUEST, forced)
662        return value
663      except:
664        objAttrs = self.getObjAttrs()
665        metaObjAttr = None
666        try:
667          if key not in objAttrs.keys():
668            metaObjAttr = self.getMetaobjAttr( self.meta_id, key)
669        except:
670          _globals.writeError( self, "[getObjProperty]: Can't get attribute from meta-objects: %s.%s"%(self.meta_id,key))
671         
672        #-- Special attributes.
673        if metaObjAttr is not None and metaObjAttr['type'] == 'method':
674          try:
675            value = _globals.dt_html(self,metaObjAttr.get('custom',''),REQUEST)
676          except:
677            value = _globals.writeError(self,'[getObjProperty]: key=%s[%s]'%(key,metaObjAttr['type']))
678        elif metaObjAttr is not None and metaObjAttr['type'] == 'py':
679          try:
680            value = metaObjAttr['py'](zmscontext=self)
681          except:
682            value = _globals.writeError(self,'[getObjProperty]: key=%s[%s]'%(key,metaObjAttr['type']))
683        elif metaObjAttr is not None and metaObjAttr['type'] == 'zpt':
684          try:
685            value = metaObjAttr['zpt'](zmscontext=self)
686            value = unicode(value).encode('utf-8')
687          except:
688            value = _globals.writeError(self,'[getObjProperty]: key=%s[%s]'%(key,metaObjAttr['type']))
689        elif metaObjAttr is not None and metaObjAttr['type'] == 'constant':
690          value = metaObjAttr.get('custom','')
691        elif metaObjAttr is not None and metaObjAttr['type'] == 'resource':
692          value = _blobfields.MyBlobWrapper(metaObjAttr.get('custom',None))
693       
694        #-- Standard attributes.
695        elif key in objAttrs.keys():
696          objAttr = objAttrs[key]
697          datatype = objAttr['datatype_key']
698          value = self.getObjAttrValue( objAttr, REQUEST)
699          if datatype == _globals.DT_TEXT and  type(value) in StringTypes:
700            try:
701              value = _globals.re_sub(self,'<dtml-sendmail(.*?)>(\r\n|\n)','<dtml-sendmail\\1>',value)
702              value = _globals.dt_html(self,value,REQUEST)
703            except:
704              value = _globals.writeError(self,'[getObjProperty]: key=%s'%key)
705       
706        #-- Undefined attributes.
707        else:
708          value = ''
709       
710        #-- [ReqBuff]: Returns value and stores it in buffer of Http-Request.
711        return self.storeReqBuff( reqBuffId, value, REQUEST)
712
713
714    # --------------------------------------------------------------------------
715    #  ObjAttrs.attr:
716    #
717    #  Get one or set one or more attributes.
718    #
719    #  attr(key) -> getObjProperty(key,REQUEST)
720    #  attr(key,value) -> setObjProperty(key,value)
721    #  attr({key0:value0,...,keyN:valueN}) -> setObjProperty(key0,value0),...
722    # --------------------------------------------------------------------------
723    def attr(self, *args, **kwargs):
724      request = self.REQUEST
725      if len(args) == 1 and type(args[0]) is str:
726        return self.getObjProperty( args[0], request, kwargs)
727      elif len(args) == 2:
728        self.setObjProperty( args[0], args[1], request.get('lang'))
729      elif len(args) == 1 and type(args[0]) is dict:
730        for key in args[0].keys():
731          self.setObjProperty( key, args[0][key], request.get('lang'))
732
733
734    """
735    ############################################################################
736    ### 
737    ###  Active
738    ###
739    ############################################################################
740    """
741
742    # --------------------------------------------------------------------------
743    #  ObjAttrs.isActive:
744    # --------------------------------------------------------------------------
745    def isActive(self, REQUEST):
746      b = True
747      if self.getType()=='ZMSRecordSet':
748        return b
749      v = self.attr('active')
750      if type(v) is bool:
751        return v
752      v = self.attr('isActive')
753      if type(v) is bool:
754        b = b and v
755      obj_vers = self.getObjVersion(REQUEST)
756      obj_attrs = self.getObjAttrs()
757      for key in ['active','attr_active_start','attr_active_end']:
758        if obj_attrs.has_key(key):
759          obj_attr = obj_attrs[key]
760          lang = REQUEST.get('lang',self.getPrimaryLanguage())
761          while True:
762            value = self._getObjAttrValue(obj_attr,obj_vers,lang)
763            empty = False
764            lang = self.getParentLanguage(lang)
765            if lang is not None:
766              empty = value is None
767            if not empty:
768              break
769          # Toggle.
770          if key == 'active':
771            b = b and value
772          # Start time.
773          elif key == 'attr_active_start':
774            if value is not None:
775              try:
776                dt = DateTime(time.mktime(value))
777                b = b and dt.isPast()
778              except:
779                # todo: consistent replacement of time by datetime
780                dtValue = datetime.datetime(value[0],value[1],value[2],value[3],value[4],value[5],value[6])
781                b = b and datetime.datetime.now() > dtValue
782          # End time.
783          elif key == 'attr_active_end':
784            if value is not None:
785              try:
786                dt = DateTime(time.mktime(value))
787                b = b and (dt.isFuture() or (dt.equalTo(dt.earliestTime()) and dt.latestTime().isFuture()))
788              except:
789                # todo: consistent replacement of time by datetime
790                dtValue = datetime.datetime(value[0],value[1],value[2],value[3],value[4],value[5],value[6])
791                b = b and dtValue < datetime.datetime.now()
792          if not b: break
793      return b
794
795
796    """
797    ############################################################################
798    #
799    #  Set
800    #
801    ############################################################################
802    """
803   
804    # --------------------------------------------------------------------------
805    #  ObjAttrs.formatObjAttrValue:
806    # --------------------------------------------------------------------------
807    def formatObjAttrValue(self, obj_attr, v, lang=None):
808     
809      #-- DATATYPE
810      datatype = obj_attr.get('datatype_key',_globals.DT_UNKNOWN)
811     
812      #-- VALUE
813      if type(v) in StringTypes:
814        chars = ''.join(filter(lambda x: x!='\t',string.whitespace))
815        v = v.strip(chars)
816      # Retrieve v from options.
817      if obj_attr.has_key('options'):
818        options = obj_attr['options']
819        try:
820          i = options.index(int(v))
821          if i%2==1: v = options[i-1]
822        except:
823          try:
824            i = options.index(str(v))
825            if i%2==1: v = options[i-1]
826          except:
827            pass
828     
829      #-- Blob-Fields
830      if datatype in _globals.DT_BLOBS:
831        if self.getType()=='ZMSRecordSet' and \
832           str(v) == str(_blobfields.createBlobField(self,datatype)):
833          l = self.getObjProperty(self.getMetaobj(self.meta_id)['attrs'][0]['id'],self.REQUEST)
834          r = filter(lambda x: v.equals(x.get(obj_attr['id'],None)),l)
835          if len( r) == 0:
836            v = None
837          else:
838            v = v._getCopy()
839            v.aq_parent = self
840            v.key = '%s:%i'%(obj_attr['id'],l.index(r[0]))
841            v.lang = lang
842        if isinstance(v,ZPublisher.HTTPRequest.FileUpload):
843          if len(getattr(v,'filename',''))==0:
844            v = None
845          else:
846            v = _blobfields.createBlobField(self,datatype,v)
847        if type(v) is dict:
848          if len(v.get('filename',''))==0:
849            v = None
850          else:
851            v = _blobfields.createBlobField(self,datatype,v)
852     
853      #-- DateTime-Fields.
854      elif datatype in _globals.DT_DATETIMES:
855        if type(v) in StringTypes:
856          fmt_str = 'DATETIME_FMT'
857          if datatype == _globals.DT_DATE:
858            fmt_str = 'DATE_FMT'
859          elif datatype == _globals.DT_TIME:
860            fmt_str = 'TIME_FMT'
861          v = self.parseLangFmtDate(v)
862        elif type(v) is not time.struct_time:
863          v = _globals.getDateTime(v)
864     
865      #-- Dictionary-Fields
866      elif datatype == _globals.DT_DICT:
867        if v is None:
868          v = {}
869        if type(v) in StringTypes:
870          try:
871           v = self.parseXmlString(self.getXmlHeader() + v)
872          except:
873            _globals.writeError( self, "[formatObjAttrValue]: can't parse dict from xml - exception ignored!")
874            pass
875        if type(v) is dict:
876          v = v.copy()
877     
878      #-- List-Fields
879      elif datatype == _globals.DT_LIST:
880        if obj_attr['repetitive'] and not type(v) is list:
881          if obj_attr['type'] in ['file','image']:
882            l = self.getObjProperty(obj_attr['id'],self.REQUEST)
883            r = filter(lambda x: v is not None and v.equals(x),l)
884            if len( r) == 0:
885              v = None
886            else:
887              v = v._getCopy()
888              v.aq_parent = self
889              v.key = '%s:%i'%(obj_attr['id'],l.index(r[0]))
890              v.lang = lang
891        else:
892          if v is None:
893            v = []
894          if type(v) in StringTypes:
895            try:
896              l = self.parseXmlString(self.getXmlHeader() + v)
897            except:
898              _globals.writeError( self, "[formatObjAttrValue]: can't parse list from xml - exception ignored!")
899              l = None
900            if l is not None:
901              v = l
902            else:
903              v = [v.strip()]
904            if type(v) is list or type(v) is tuple:
905              v = self.copy_list(v)
906     
907      #-- Integer-Fields
908      elif datatype in _globals.DT_INTS:
909        if type(v) in StringTypes and len(v) > 0:
910          if v[-1] == '.':
911            v = v[:-1]
912          v = int(v)
913     
914      #-- Float-Fields
915      elif datatype == _globals.DT_FLOAT:
916        if type(v) in StringTypes and len(v) > 0:
917          v = float(v)
918     
919      #-- String-Fields.
920      elif datatype in _globals.DT_STRINGS:
921        if v is None:
922          v = ''
923     
924      #-- Text-Fields
925      if datatype == _globals.DT_TEXT:
926        # Inline-links: getLinkUrl (deprecated!)
927        i = -1
928        start = '{$'
929        end = '}'
930        while True:
931          i = v.find( start, i + 1)
932          j = v.find( end, i + 1)
933          if i < 0 or j < 0:
934            break
935          ref_url = v[i:j+1]
936          ref_obj = self.getLinkObj(ref_url)
937          if ref_obj is not None:
938            # Repair link.
939            ref_url = self.getRefObjPath(ref_obj)
940            v = v[:i] + ref_url + v[j+1:]
941          elif ref_url.find('{$') == 0 and ref_url.find('{$__') < 0:
942            # Broken link.
943            ref_url = '{$__' + ref_url[2:-1] + '__}'
944            v = v[:i] + ref_url + v[j+1:]
945     
946      #-- Url-Fields
947      if datatype == _globals.DT_URL and v.startswith('{$') and not v.startswith('{$__') and self.getConfProperty('ZMS.InternalLinks.autocorrection',0)==1:
948        v = self.validateLinkObj(v)
949     
950      # Hook for custom formatting.
951      name = 'formatCustomObjAttrValue'
952      if hasattr(self,name):
953        v = getattr(self,name)( context=self, obj_attr=obj_attr, v=v)
954     
955      return v
956
957
958    # --------------------------------------------------------------------------
959    #  ObjAttrs.setReqProperty:
960    #
961    #  Assigns value to specified property from Request-Object.
962    # --------------------------------------------------------------------------
963    def setReqProperty(self, key, REQUEST, forced=0):
964   
965      #-- REQUEST
966      lang = REQUEST['lang']
967     
968      #-- DEFINTION
969      obj_attr = self.getObjAttr(key)
970      attr = self.getObjAttrName(obj_attr,lang)
971      elName = self.REQUEST.get('objAttrNamePrefix','') + attr
972     
973      #-- ENABLED
974      enabled = not self.isDisabledAttr(obj_attr,REQUEST)
975     
976      #-- DATATYPE
977      datatype = obj_attr['datatype_key']
978     
979      #-- RETURN
980      if ( not enabled) or \
981         ( not obj_attr['xml']) or \
982         ( obj_attr['id'].find('_') == 0 and not REQUEST.form.has_key(elName)) or \
983         ( datatype == _globals.DT_UNKNOWN):
984        if not forced:
985          return
986     
987      #-- VALUE
988      set, value =False, REQUEST.get(elName,None)
989     
990      #-- Blob-Fields
991      if datatype in _globals.DT_BLOBS:
992       
993        # Upload
994        if isinstance(value,ZPublisher.HTTPRequest.FileUpload) and len(value.filename) > 0:
995          set, value = True, value
996       
997        # Delete
998        elif REQUEST.has_key('del_%s'%attr) and int(REQUEST['del_%s'%attr]) == 1:
999          set, value = True, None
1000       
1001        # Preload
1002        else:
1003          SESSION = REQUEST.get('SESSION',None)
1004          form_id = REQUEST.get('form_id',None)
1005          if SESSION is not None and form_id is not None:
1006            session_id = REQUEST.get('session_id',SESSION.getId())
1007            temp_folder = self.temp_folder
1008            id = session_id + '_' + form_id + '_' + key
1009            if id in temp_folder.objectIds():
1010              o = getattr( temp_folder, id)
1011              f = o.data
1012              filename = getattr( temp_folder, id).title
1013              mt, enc = _globals.guess_contenttype( filename, f)
1014              set, value = True, {'data':f,'filename':filename,'content_type':mt}
1015              if not self.pilutil().enabled() and datatype == _globals.DT_IMAGE and REQUEST.get('width_%s'%attr) and REQUEST.get('height_%s'%attr):
1016                w = REQUEST['width_%s'%attr]
1017                h = REQUEST['height_%s'%attr]
1018                if w != int(o.width) or h != int(o.height):
1019                  #-- print '_objattrs: resize',o.width,'x',o.height,' to ',w,'x',h
1020                  value = _blobfields.createBlobField( self, datatype, value)
1021                  value.width = w
1022                  value.height = h
1023              temp_folder.manage_delObjects([id])
1024     
1025      #-- Integer-Fields
1026      elif datatype in _globals.DT_INTS:
1027        if value is not None:
1028          if type(value) is str and len(value) == 0:
1029            set, value = True, None
1030          else:
1031            set, value = True, int(value)
1032     
1033      #-- Float-Fields
1034      elif datatype == _globals.DT_FLOAT:
1035        if value is not None:
1036          if type(value) is str and len(value) == 0:
1037            set, value = True, None
1038          else:
1039            set, value = True, float(value)
1040     
1041      #-- Other-Fields
1042      else:
1043        set, value = True, self.formatObjAttrValue(obj_attr,value,lang)
1044     
1045      #-- SET?
1046      if set:
1047        _globals.writeLog( self, "[setReqProperty] %s=%s"%(key,str(value)))
1048        self.setObjProperty(key,value,lang)
1049
1050
1051    # --------------------------------------------------------------------------
1052    #  ObjAttrs.setObjProperty:
1053    #
1054    #  Assigns value to specified property.
1055    #
1056    #  @deprecated: use attr(key,value) instead!
1057    # --------------------------------------------------------------------------
1058    def setObjProperty(self, key, value, lang=None, forced=0):
1059     
1060      #-- [ReqBuff]: Clear buffered value from Http-Request.
1061      reqBuffId = '%s_%s'%('getObjProperty',key)
1062      self.clearReqBuff(reqBuffId,self.REQUEST)
1063     
1064      #-- CUSTOM
1065      if key not in self.getObjAttrs().keys():
1066        self.REQUEST.set('pKey',key)
1067        self.REQUEST.set('pValue',value)
1068        self.getObjProperty('setObjProperty',self.REQUEST)
1069        return
1070     
1071      #-- DEFINITION
1072      obj_attr = self.getObjAttr(key)
1073     
1074      #-- DATATYPE
1075      datatype = obj_attr['datatype_key']
1076     
1077      #-- VALUE
1078      value = self.formatObjAttrValue(obj_attr,value,lang)
1079     
1080      #-- Url-Fields
1081      if datatype == _globals.DT_URL:
1082        # Unregister old reference.
1083        req = {'lang' : lang, 'prevew' : 'preview'}
1084        old_value = self.getObjProperty(key,req)
1085        ref_obj = self.getLinkObj(old_value)
1086        if ref_obj is not None:
1087          ref_obj.unregisterRefObj(self,self.REQUEST)
1088        # Register new reference.
1089        ref_obj = self.getLinkObj(value)
1090        if ref_obj is not None:
1091          ref_obj.registerRefObj(self,self.REQUEST)
1092        value = self.validateLinkObj(value)
1093     
1094      #-- Notify metaobj_manager.
1095      self.notifyMetaobjAttrAboutValue( self.meta_id, key, value)
1096     
1097      #-- SET!
1098      _globals.writeLog( self, "[setObjProperty]: %s(%s)=%s"%(key,str(datatype),str(value)))
1099      ob = self.getObjVersion({'preview':'preview'})
1100      setobjattr(self,ob,obj_attr,value,lang)
1101      if forced:
1102        ob = self.getObjVersion()
1103        setobjattr(self,ob,obj_attr,value,lang)
1104
1105
1106    ############################################################################
1107    #  ObjAttrs.preloadObjProperty:
1108    #
1109    #  Preload property.
1110    ############################################################################
1111    def preloadObjProperty(self, REQUEST, RESPONSE=None):
1112      """ ObjAttrs.preloadObjProperty """
1113      content_type = 'text/plain'
1114      message = '{"success":true}'
1115      # Additional parameters.
1116      for qs in REQUEST['QUERY_STRING'].split('&'):
1117        e = qs.find('=')
1118        if e >= 0:
1119          k = qs[:e]
1120          v = qs[e+1:]
1121          REQUEST.set(k,v)
1122     
1123      # Mandatory parameters.
1124      lang = REQUEST['lang']
1125      key = REQUEST['key']
1126     
1127      dataRequestKey = REQUEST.get('dataRequestKey')
1128      filenameUnescape = REQUEST.get('filenameUnescape')
1129      if dataRequestKey:
1130        value = REQUEST[dataRequestKey]
1131        if isinstance(value,ZPublisher.HTTPRequest.FileUpload):
1132          filename = value.filename
1133        else:
1134          filename = value
1135          value = REQUEST['BODY']
1136          if filenameUnescape:
1137            filename = _globals.unescape(filename)
1138      else:
1139        value = REQUEST['userfile[0]']
1140        filename = value.filename
1141      blob = self.ImageFromData(value,filename)
1142      filename = blob.getFilename()
1143     
1144      # Preload to temp-folder.
1145      session_id = REQUEST['session_id']
1146      form_id = REQUEST['form_id']
1147      temp_folder = self.temp_folder
1148      id = session_id + '_' + form_id + '_' + key
1149      if id in temp_folder.objectIds():
1150        temp_folder.manage_delObjects([id])
1151      meta_id = REQUEST.get('meta_id',self.meta_id)
1152      obj_attr = self.getObjAttr(key,meta_id)
1153      datatype = obj_attr['datatype_key']
1154      if datatype == _globals.DT_IMAGE:
1155        file = temp_folder.manage_addImage( id=id, title=filename, file=value)
1156      else:
1157        file = temp_folder.manage_addFile( id=id, title=filename, file=value)
1158     
1159      if REQUEST.get('set'):
1160        self.setReqProperty(key,REQUEST)
1161        message = self.getZMILangStr( 'MSG_UPLOADED')+'('+self.getLangFmtDate(time.time())+')'
1162     
1163      # Return with success.
1164      RESPONSE.setHeader('Content-Type',content_type)
1165      return message
1166
1167
1168    def manage_changeTempBlobjProperty(self, lang, key, form_id, action, REQUEST, RESPONSE=None):
1169      """ ObjAttrs.manage_changeTempBlobjProperty """
1170      rtn = {}
1171      # Mandatory parameters.
1172      SESSION = REQUEST.get('SESSION',None)
1173      if SESSION is not None:
1174        session_id = SESSION.getId()
1175        temp_folder = self.temp_folder
1176        id = session_id + '_' + form_id + '_' + key
1177        src = self.getTempBlobjPropertyUrl( format=None, REQUEST=REQUEST, RESPONSE=RESPONSE)['src']
1178        file = getattr( temp_folder, id)
1179        orig = self.ImageFromData(file.data,file.title)
1180        orig.lang = lang
1181        if action == 'preview':
1182          maxdim = self.getConfProperty('InstalledProducts.pil.thumbnail.max',100)
1183          blob = self.pilutil().thumbnail( orig, maxdim)
1184          thumbkey = key
1185          for suffix in ['hires','superres']:
1186            if thumbkey.endswith(suffix):
1187              thumbkey = thumbkey[:-len(suffix)]
1188              break
1189          thumbid = session_id + '_' + form_id + '_' + thumbkey
1190          if thumbid in temp_folder.objectIds():
1191            temp_folder.manage_delObjects([thumbid])
1192          temp_folder.manage_addImage( id=thumbid, title=blob.getFilename(), file=blob.getData())
1193          file = getattr( temp_folder, thumbid)
1194          meta_id = REQUEST.get('meta_id',self.meta_id)
1195          obj_attr = self.getObjAttr(thumbkey,meta_id)
1196          elName = self.getObjAttrName(obj_attr,lang)
1197          rtn['elName'] = elName
1198          rtn['height'] = int(file.getProperty('height'))
1199          rtn['width'] = int(file.getProperty('width'))
1200          rtn['filename'] = blob.getFilename()
1201          rtn['src'] = self.url_append_params(file.absolute_url(),{'ts':time.time()})
1202          # extra
1203          rtn['lang'] = thumbkey
1204          rtn['key'] = thumbkey
1205          rtn['form_id'] = form_id
1206        elif action == 'crop':
1207          x0 = REQUEST['x0']
1208          y0 = REQUEST['y0']
1209          x1 = REQUEST['x1']
1210          y2 = REQUEST['y2']
1211          box = (x0, y0, x1, y2)
1212          blob = self.pilutil().crop( orig, box)
1213          file.manage_upload(blob.getData())
1214          rtn['height'] = y2-y0
1215          rtn['width'] = x1-x0
1216          rtn['filename'] = blob.getFilename()
1217          rtn['src'] = src
1218        elif action == 'resize':
1219          width = REQUEST['width']
1220          height = REQUEST['height']
1221          size = (width,height)
1222          blob = self.pilutil().resize( orig, size)
1223          file.manage_upload(blob.getData())
1224          rtn['height'] = height
1225          rtn['width'] = width
1226          rtn['filename'] = blob.getFilename()
1227          rtn['src'] = src
1228      # Return JSON.
1229      return self.str_json(rtn)
1230
1231
1232    def getTempBlobjPropertyUrl(self, format='json', REQUEST=None, RESPONSE=None):
1233      """ ObjAttrs.getTempBlobjPropertyUrl """
1234      rtn = {}
1235      # Mandatory parameters.
1236      lang = REQUEST['lang']
1237      key = REQUEST['key']
1238      SESSION = REQUEST.get('SESSION',None)
1239      form_id = REQUEST.get('form_id',None)
1240      if SESSION is not None and form_id is not None:
1241        session_id = SESSION.getId()
1242        temp_folder = self.temp_folder
1243        id = session_id + '_' + form_id + '_' + key
1244        if id not in temp_folder.objectIds():
1245          obj_attr = self.getObjAttr(key)
1246          datatype = obj_attr['datatype_key']
1247          blob = self.getObjProperty(key,REQUEST)
1248          filename = blob.getFilename()
1249          value = blob.getData()
1250          if datatype == _globals.DT_IMAGE:
1251            file = temp_folder.manage_addImage( id=id, title=filename, file=value)
1252          else:
1253            file = temp_folder.manage_addFile( id=id, title=filename, file=value)
1254        file = getattr( temp_folder, id)
1255        if file.meta_type == 'Image':
1256          rtn['height'] = int(file.getProperty('height'))
1257          rtn['width'] = int(file.getProperty('width'))
1258        rtn['content_type'] = file.content_type
1259        rtn['filename'] = file.title
1260        rtn['src'] = self.url_append_params(file.absolute_url(),{'ts':time.time()})
1261      # Return JSON.
1262      if format == 'json':
1263        rtn = self.str_json(rtn)
1264      return rtn
1265
1266
1267    def clearTempBlobjProperty(self, format='json', REQUEST=None, RESPONSE=None):
1268      """ ObjAttrs.clearTempBlobjProperty """
1269      rtn = {}
1270      # Mandatory parameters.
1271      lang = REQUEST['lang']
1272      key = REQUEST['key']
1273      SESSION = REQUEST.get('SESSION',None)
1274      form_id = REQUEST.get('form_id',None)
1275      if SESSION is not None and form_id is not None:
1276        session_id = SESSION.getId()
1277        temp_folder = self.temp_folder
1278        id = session_id + '_' + form_id + '_' + key
1279        if id in temp_folder.objectIds():
1280          temp_folder.manage_delObjects([id])
1281      # Return JSON.
1282      if format == 'json':
1283        rtn = self.str_json(rtn)
1284      return rtn
1285
1286
1287    # --------------------------------------------------------------------------
1288    #  ObjAttrs.convertObjPropertyUtf8
1289    # --------------------------------------------------------------------------
1290    def convertObjPropertyUtf8(self, key):
1291      obj_attr = self.getObjAttr(key)
1292      for obj_vers in self.getObjVersions():
1293        if obj_attr['multilang']:
1294          for langId in self.getLangIds():
1295            setutf8attr(self, obj_vers, obj_attr, langId)
1296        else:
1297          langId = self.getPrimaryLanguage()
1298          setutf8attr(self, obj_vers, obj_attr, langId)
1299
1300
1301    # --------------------------------------------------------------------------
1302    #  ObjAttrs.utf8
1303    # --------------------------------------------------------------------------
1304    def utf8(self, s, encoding='latin-1'):
1305      return utf8(s, encoding)
1306
1307
1308    """
1309    ############################################################################
1310    #
1311    #  C L O N E
1312    #
1313    ############################################################################
1314    """
1315   
1316    # --------------------------------------------------------------------------
1317    #  ObjAttrs.cloneObjAttrs:
1318    #
1319    #  Clone object-attributes.
1320    # --------------------------------------------------------------------------
1321    def cloneObjAttrs(self, src, dst, REQUEST={}):
1322      _globals.writeBlock( self, "[cloneObjAttrs]: Clone object-attributes from '%s' to '%s'"%(str(src),str(dst)))
1323   
1324      #-- REQUEST
1325      prim_lang = self.getPrimaryLanguage()
1326      lang = REQUEST.get('lang',prim_lang)
1327     
1328      #-- Clone
1329      keys = self.getObjAttrs().keys()
1330      if self.getType()=='ZMSRecordSet':
1331        keys = self.difference_list( keys, self.getMetaobjAttrIds(self.meta_id)[1:])
1332      for key in keys:
1333        obj_attr = self.getObjAttr(key)
1334        # Multi-Language Attributes.
1335        if obj_attr['multilang']:
1336          for s_lang in self.getLangIds():
1337            if lang in ['*',prim_lang,s_lang]:
1338              cloneobjattr(self,src,dst,obj_attr,s_lang)
1339        # Others.
1340        else:
1341          coverage = getattr(src,'attr_dc_coverage','')
1342          if coverage is None or \
1343             coverage == '' or \
1344             type(coverage) is not str:
1345            coverage = 'global.%s'%prim_lang
1346          s_lang = coverage[coverage.find('.')+1:]
1347          if lang in ['*',prim_lang,s_lang]:
1348            cloneobjattr(self,src,dst,obj_attr,lang)
1349
1350
1351################################################################################
1352################################################################################
1353###
1354###   Object Attributes Manager
1355###
1356################################################################################
1357################################################################################
1358class ObjAttrsManager:
1359
1360    # --------------------------------------------------------------------------
1361    #  ObjAttrsManager.synchronizeObjAttr:
1362    #
1363    #  Synchronizes object-attribute.
1364    # --------------------------------------------------------------------------
1365    def synchronizeObjAttr(self, attr):
1366      try:
1367        if attr['type'] in ZMSMetaobjManager.ZMSMetaobjManager.valid_types:
1368          dct = {}
1369          dct['id'] = attr['id']
1370          dct['name'] = attr.get('name','?')
1371          dct['type'] = attr['type']
1372          dct['key'] = attr['id']
1373          dct['xml'] = attr['id'] not in ['created_uid','created_dt','change_uid','change_dt','work_uid','work_dt','internal_dict','change_history','master_version','major_version','minor_version']
1374          dct['lang_inherit'] = attr['id'] not in ['change_uid','change_dt','work_uid','work_dt','internal_dict']
1375          dct['datatype'] = attr['type']
1376          if attr['type'] in ['autocomplete','password','select']:
1377            dct['type'] = attr['type']
1378            dct['datatype'] = 'string'
1379          elif attr['type'] in ['richtext']:
1380            dct['type'] = attr['type']
1381            dct['datatype'] = 'text'
1382          elif attr['type'] in ['multiautocomplete','multiselect']:
1383            dct['type'] = attr['type']
1384            dct['datatype'] = 'list'
1385          elif attr.get('default','') != '':
1386            dct['default'] = attr['default']
1387          elif attr.get('repetitive',0):
1388            dct['datatype'] = 'list'
1389          dct['mandatory'] = attr.get('mandatory',0)
1390          dct['multilang'] = attr.get('multilang',0)
1391          dct['repetitive'] = attr.get('repetitive',0)
1392          if len(attr.get('keys',[]))>0:
1393            options = []
1394            for option in attr['keys']:
1395              options.append(option)
1396              options.append(option)
1397            dct['options'] = options
1398          dct['datatype_key'] = _globals.datatype_key(dct['datatype'])
1399          return dct
1400      except:
1401        _globals.writeError( self, '[synchronizeObjAttr]')
1402      return None
1403
1404    def synchronizeObjAttrs(self, sync_id=None):
1405      """
1406      Synchronizes dictionary of object-attributes.
1407      @param sync_id: meta-id of content-object, if None synchronize all.
1408      """
1409      rtn = []
1410      rtn.append('[%s.synchronizeObjAttrs]: %s'%(self.absolute_url(),str(sync_id)))
1411      _globals.writeLog( self, '[synchronizeObjAttrs]')
1412     
1413      # Prepare defaults.
1414      defaults_obj_attrs = {}
1415      defaults = [
1416        # Coverage
1417        { 'id':'attr_dc_coverage', 'type':'string'},
1418        # Changed by
1419        { 'id':'created_uid', 'type':'string'},
1420        { 'id':'created_dt', 'type':'datetime'},
1421        { 'id':'change_uid','type':'string', 'multilang':1},
1422        { 'id':'change_dt','type':'datetime', 'multilang':1},
1423        # Version info
1424        { 'id':'change_history', 'type':'list', 'default':[]},
1425        { 'id':'master_version', 'type':'int', 'default':0},
1426        { 'id':'major_version', 'type':'int', 'default':0},
1427        { 'id':'minor_version', 'type':'int', 'default':0},
1428        # Active
1429        { 'id':'active', 'type':'boolean', 'multilang':1, 'default':1},
1430        { 'id':'attr_active_start', 'type':'datetime', 'multilang':1},
1431        { 'id':'attr_active_end','type':'datetime', 'multilang':1},
1432        # Workflow
1433        { 'id':'work_uid','type':'string', 'multilang':1},
1434        { 'id':'work_dt','type':'datetime', 'multilang':1},
1435        # Internal dictionary
1436        { 'id':'internal_dict', 'type':'dictionary', 'default':{}},
1437      ]
1438      for attr in defaults:
1439        dct = self.synchronizeObjAttr( attr)
1440        if type( dct) is dict:
1441          defaults_obj_attrs[dct['id']] = dct
1442     
1443      # Process meta-model.
1444      if sync_id is None or sync_id == [ None]:
1445        self.dObjAttrs = {}
1446        meta_ids = self.dGlobalAttrs.keys()
1447        for meta_id in self.getMetaobjIds( sort=0):
1448          if meta_id not in meta_ids:
1449            meta_ids.append( meta_id)
1450      else:
1451        if not type(sync_id) is list:
1452          sync_id = [sync_id]
1453        meta_ids = sync_id
1454      for meta_id in meta_ids:
1455        if meta_id in self.dGlobalAttrs.keys():
1456          obj_attrs = {}
1457          for key in defaults_obj_attrs.keys():
1458            obj_attr = defaults_obj_attrs[key]
1459            if obj_attr['id'].find('work_') < 0 or meta_id in ['ZMSCustom','ZMSLinkElement'] or self.getMetaobj(meta_id).get('type') == 'ZMSDocument':
1460              obj_attrs[key] = obj_attr.copy()
1461        else:
1462          obj_attrs = self.dObjAttrs['ZMSCustom'].copy()
1463        for key in self.getMetaobjAttrIds( meta_id):
1464          attr = self.getMetaobjAttr( meta_id, key)
1465          dct = self.synchronizeObjAttr( attr)
1466          if type( dct) is dict:
1467            obj_attrs[key] = dct
1468          elif obj_attrs.has_key(key):
1469            del obj_attrs[key]
1470        self.dObjAttrs[meta_id] = obj_attrs
1471     
1472      # Make persistent.
1473      self.dObjAttrs = self.dObjAttrs.copy()
1474     
1475      # Process clients.
1476      for portalClient in self.getPortalClients():
1477        try:
1478          b = False
1479          if not b:
1480            b = sync_id is None
1481          if not b:
1482            metaObjIds = portalClient.getMetaobjIds(sort=0)
1483            for id in sync_id:
1484              if not b:
1485                b = id in metaObjIds and portalClient.getMetaobj(id).get('acquired',0)==1
1486          if b:
1487            rtn.append(portalClient.synchronizeObjAttrs(sync_id))
1488        except:
1489          _globals.writeError( self, '[synchronizeObjAttrs]: Can\'t process %s'%portalClient.absolute_url())
1490     
1491      return '\n'.join(rtn)
1492
1493################################################################################
Note: See TracBrowser for help on using the repository browser.