source: ZMS/trunk/ZMSMetaobjManager.py @ 1877

Revision 1877, 60.4 KB checked in by fhoffmann, 11 days ago (diff)

Removed automatic zsql connection correction in content models

Line 
1################################################################################
2# ZMSMetaobjManager.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
20# Imports.
21from zope.interface import implements
22from Products.ExternalMethod import ExternalMethod
23from Products.PageTemplates import ZopePageTemplate
24from Products.PythonScripts import PythonScript
25from cStringIO import StringIO
26import ZPublisher.HTTPRequest
27import copy
28import os
29import sys
30import time
31import zExceptions
32# Product Imports.
33import _blobfields
34import _fileutil
35import _globals
36import _ziputil
37import IZMSSvnInterface
38
39
40# ------------------------------------------------------------------------------
41#  Synchronize type.
42# ------------------------------------------------------------------------------
43def syncType( self, meta_id, attr):
44  try:
45    attr_id = attr['id']
46    if attr['type'] in self.valid_zopetypes:
47      container = self.getHome()
48      for ob_id in attr_id.split('/')[:-1]:
49         container = getattr( container, ob_id)
50      ob_id = attr['id'].split('/')[-1]
51      ob = getattr( container, ob_id)
52      if ob.meta_type in [ 'DTML Method', 'DTML Document']:
53        attr['custom'] = ob.raw
54      elif ob.meta_type in [ 'Folder']:
55        zexp = ob.aq_parent.manage_exportObject( id=ob.id, download=1)
56        blob = _blobfields.createBlobField( self,_globals.DT_FILE, zexp, mediadbStorable=False)
57        attr['custom'] = blob
58      elif ob.meta_type in [ 'Page Template']:
59        attr['custom'] = unicode(ob.read()).encode('utf-8')
60      elif ob.meta_type in [ 'Script (Python)']:
61        attr['custom'] = ob.read()
62      elif ob.meta_type in [ 'Z SQL Method']:
63        connection = ob.connection_id
64        params = ob.arguments_src
65        attr['custom'] = '<connection>%s</connection>\n<params>%s</params>\n%s'%(connection,params,ob.src)
66    else:
67      ob = getattr( self, meta_id+'.'+attr_id, None)
68      if ob is None:
69        return
70      if attr['type'] == 'method':
71        attr['custom'] = ob.raw
72      elif attr['type'] == 'py':
73        attr['py'] = ob
74        attr['custom'] = ob.read()
75      elif attr['type'] == 'zpt':
76        attr['zpt'] = ob
77        attr['custom'] = unicode(ob.read()).encode('utf-8')
78      elif attr['type'] == 'interface':
79        attr['name'] = ob.raw
80      else:
81        attr['custom'] = ob
82  except:
83    value = _globals.writeError(self,'[syncType]')
84
85
86# ------------------------------------------------------------------------------
87#  Search tree for instance of object with given meta-ids.
88# ------------------------------------------------------------------------------
89def findMetaobj(self, ids):
90  if self.meta_id in ids:
91    return self
92  for child in self.getChildNodes():
93    ob = findMetaobj(child, ids)
94    if ob is not None:
95      return ob
96  return None
97
98
99################################################################################
100################################################################################
101###
102###   Class
103###
104################################################################################
105################################################################################
106class ZMSMetaobjManager:
107    implements(IZMSSvnInterface.IZMSSvnInterface)
108
109    # Globals.
110    # --------
111    valid_types =     ['amount','autocomplete','boolean','color','date','datetime','dictionary','file','float','identifier','image','int','list','multiautocomplete','multiselect','password','richtext','select','string','text','time','url','xml']
112    valid_xtypes =    ['constant','delimiter','hint','interface','method','py','zpt','resource']
113    valid_datatypes = valid_types+valid_xtypes
114    valid_datatypes.sort()
115    valid_objtypes =  [ 'ZMSDocument', 'ZMSObject', 'ZMSTeaserElement', 'ZMSRecordSet', 'ZMSResource', 'ZMSReference', 'ZMSLibrary', 'ZMSPackage', 'ZMSModule']
116    valid_zopetypes = [ 'DTML Method', 'DTML Document', 'External Method', 'Folder', 'Page Template', 'Script (Python)', 'Z SQL Method']
117
118
119    ############################################################################
120    #
121    #  XML IM/EXPORT
122    #
123    ############################################################################
124
125    # --------------------------------------------------------------------------
126    #  ZMSMetaobjManager.importMetaobjXml
127    # --------------------------------------------------------------------------
128
129    def _importMetaobjXml(self, item, zms_system=0, createIfNotExists=1, createIdsFilter=None):
130      id = item['key']
131      meta_types = self.model.keys()
132      ids = filter( lambda x: self.model[x].get('zms_system',0)==1, meta_types)
133      if (createIfNotExists == 1 or (id in ids and item.get('value').get('package')==self.model.get(id).get('package'))) and \
134         (createIdsFilter is None or (id in createIdsFilter)):
135        # Register Meta Attributes.
136        metadictAttrs = []
137        if id in meta_types:
138          valid_types = self.valid_datatypes+self.valid_zopetypes+meta_types+['*']
139          metaObj = self.getMetaobj( id)
140          for metaObjAttr in metaObj['attrs']:
141            if metaObjAttr['type'] not in valid_types+metadictAttrs:
142              metadictAttrs.append( metaObjAttr['type'])
143        newDtml = item.get('dtml')
144        newValue = item.get('value')
145        newAttrs = newValue.get('attrs',newValue.get('__obj_attrs__'))
146        newValue['attrs'] = []
147        newValue['id'] = id
148        newValue['enabled'] = newValue.get('enabled',item.get('enabled',1))
149        newValue['zms_system'] = item.get('zms_system',zms_system)
150        # Delete Object.
151        oldAttrs = None
152        if id in ids:
153          if zms_system == 1:
154            oldAttrs = self.getMetaobj( id)['attrs']
155          self.delMetaobj( id)
156        # Set Object.
157        self.setMetaobj( newValue)
158        # Set Attributes.
159        attr_ids = []
160        for attr in newAttrs:
161          # Mandatory.
162          attr_id = attr.get('id')
163          newName = attr.get('name')
164          newMandatory = attr.get('mandatory')
165          newMultilang = attr.get('multilang')
166          newRepetitive = attr.get('repetitive')
167          newType = attr.get('type')
168          # Optional.
169          newKeys = attr.get('keys',[])
170          newCustom = attr.get('custom','')
171          newDefault = attr.get('default','')
172          # Old Attribute.
173          if type(oldAttrs) is list and len(oldAttrs) > 0:
174            while len(oldAttrs) > 0 and not (attr_id == oldAttrs[0]['id'] and newType == oldAttrs[0]['type']):
175              oldAttr = oldAttrs[0]
176              # Set Attribute.
177              if oldAttr['id'] not in attr_ids:
178                self.setMetaobjAttr( id, None, oldAttr['id'], oldAttr['name'], oldAttr['mandatory'], oldAttr['multilang'], oldAttr['repetitive'], oldAttr['type'], oldAttr['keys'], oldAttr['custom'], oldAttr['default'], zms_system)
179                attr_ids.append(oldAttr['id'])
180              # Deregister Meta Attribute.
181              if oldAttr['id'] in metadictAttrs:
182                metadictAttrs.remove(oldAttr['id'])
183              oldAttrs.remove( oldAttr)
184            if len(oldAttrs) > 0:
185              oldAttrs.remove( oldAttrs[0])
186          # Set Attribute.
187          if attr_id not in attr_ids:
188            self.setMetaobjAttr( id, attr_id, attr_id, newName, newMandatory, newMultilang, newRepetitive, newType, newKeys, newCustom, newDefault, zms_system)
189            attr_ids.append(attr_id)
190          # Deregister Meta Attribute.
191          if attr_id in metadictAttrs:
192            metadictAttrs.remove(attr_id)
193        # Set Meta Attributes.
194        for attr_id in metadictAttrs:
195          newName = attr_id
196          newMandatory = 0
197          newMultilang = 0
198          newRepetitive = 0
199          newType = attr_id
200          newKeys = []
201          newCustom = ''
202          newDefault = ''
203          # Set Attribute.
204          if attr_id not in attr_ids:
205            self.setMetaobjAttr( id, None, attr_id, newName, newMandatory, newMultilang, newRepetitive, newType, newKeys, newCustom, newDefault)
206            attr_ids.append(attr_id)
207        # Set Template (backwards compatibility).
208        if newValue['type'] not in [ 'ZMSLibrary', 'ZMSModule', 'ZMSPackage'] and newDtml is not None:
209          tmpltId = 'standard_html'
210          tmpltName = 'Template: %s'%newValue['name']
211          tmpltCustom = newDtml
212          newType = 'DTML Method'
213          newKeys = []
214          newDefault = ''
215          self.setMetaobjAttr(id,tmpltId,tmpltId,tmpltName,0,0,0, newType, newKeys, tmpltCustom, newDefault, zms_system)
216      return id
217
218    def importMetaobjXml(self, xml, REQUEST=None, zms_system=0, createIfNotExists=1, createIdsFilter=None):
219      self.REQUEST.set( '__get_metaobjs__', True)
220      ids = []
221      v = self.parseXmlString( xml, mediadbStorable=False)
222      if not type(v) is list:
223        v = [v]
224      for item in v:
225        id = self._importMetaobjXml(item,zms_system,createIfNotExists,createIdsFilter)
226        ids.append( id)
227      if len( ids) == 1:
228        ids = ids[ 0]
229      return ids
230
231    def exportMetaobjXml(self, ids, REQUEST=None, RESPONSE=None):
232      value = []
233      for id in ids:
234        metaObj = self.getMetaobj( id)
235        if metaObj['type'] == 'ZMSPackage':
236          for pkgMetaObjId in self.getMetaobjIds():
237              pkgMetaObj = self.getMetaobj( pkgMetaObjId)
238              if pkgMetaObj[ 'package'] == metaObj[ 'id']:
239                ids.append( pkgMetaObjId)
240      keys = self.model.keys()
241      keys.sort()
242      revision = '0.0.0'
243      for id in keys:
244        if id in ids or len(ids) == 0:
245          ob = copy.deepcopy(self.__get_metaobj__(id))
246          revision = ob.get( 'revision', revision)
247          attrs = []
248          for attr in ob['attrs']:
249            attr_id = attr['id']
250            syncType( self, id, attr)
251            for key in ['keys','custom','default']:
252              if attr.has_key(key) and not attr[key]:
253                del attr[key]
254            for key in ['py','zpt']:
255              if attr.has_key(key):
256                del attr[key]
257            attrs.append( attr)
258          ob['__obj_attrs__'] = attrs
259          for key in ['attrs','zms_system','acquired']:
260            if ob.has_key(key):
261              del ob[key]
262          # Value.
263          value.append({'key':id,'value':ob})
264      # XML.
265      if len(value)==1:
266        value = value[0]
267        filename = '%s-%s.metaobj.xml'%(ids[0],revision)
268      else:
269        filename = 'export.metaobj.xml'
270      content_type = 'text/xml; charset=utf-8'
271      export = self.getXmlHeader() + self.toXmlString(value,1)
272     
273      if RESPONSE:
274        RESPONSE.setHeader('Content-Type',content_type)
275        RESPONSE.setHeader('Content-Disposition','attachment;filename="%s"'%filename)
276      return export
277
278
279    ############################################################################
280    #
281    #  IZMSSvnInterface
282    #
283    ############################################################################
284
285    # --------------------------------------------------------------------------
286    #  ZMSMetaobjManager.svnCopy
287    # --------------------------------------------------------------------------
288    def svnCopy(self, node, path, ids=[], excl_ids=[]):
289      l = []
290      for id in self.getMetaobjIds():
291        metaObj = self.getMetaobj(id)
292        if not metaObj.get('acquired'):
293          if metaObj.get('package') == '' or metaObj.get('type') == 'ZMSPackage':
294            action = None
295            path_id = id+'.metaobj.xml'
296            filepath = path+'/'+self.id+'/'+path_id
297            filemrevision = None
298            mrevision = metaObj.get('revision','0.0.0')
299            if os.path.exists( filepath):
300              filexml = self.parseXmlString( open(filepath), mediadbStorable=False)
301              if type(filexml) is list:
302                filexml = filter(lambda x: x['value']['type']=='ZMSPackage',filexml)[0]
303              filemrevision = filexml['value'].get('revision','0.0.0')
304              if mrevision > filemrevision:
305                action = 'refresh'
306              elif mrevision < filemrevision:
307                action = 'conflict'
308            else:
309              action = 'add'
310            if action:
311              l.append({'action':action,'filepath':filepath,'mrevision':mrevision,'filemrevision':filemrevision,'meta_type':self.meta_type})
312              if filepath in ids or '*' in ids:
313                xml = self.exportMetaobjXml([id])
314                _fileutil.exportObj(xml,filepath)
315      return l
316
317
318    # --------------------------------------------------------------------------
319    #  ZMSMetaobjManager.svnUpdate
320    # --------------------------------------------------------------------------
321    def svnUpdate(self, node, path, ids=[], excl_ids=[]):
322      l = []
323      suffix = '.metaobj.xml'
324      # Changed resources.
325      for filename in filter( lambda x: x!='.svn', os.listdir(path)):
326        action = None
327        error_message = None
328        filepath = path+'/'+filename
329        file = open(filepath)
330        # Execute action.
331        if filepath in ids or '*' in ids:
332          self.metaobj_manager.importMetaobjXml( file)
333        elif filepath.endswith(suffix):
334          try:
335            filexml = self.parseXmlString( file, mediadbStorable=False)
336          except:
337            filexml = None
338            error_message = _globals.writeError(self,'')
339          if filexml is None:
340            action = 'error'
341          else:
342            if type(filexml) is list:
343              filexml = filter(lambda x: x['value']['type']=='ZMSPackage',filexml)[0]
344            mrevision = None
345            filemrevision = filexml['value'].get('revision','0.0.0')
346            metaObjId = filename[:-len(suffix)]
347            if metaObjId in self.getMetaobjIds():
348              metaObj = self.getMetaobj(metaObjId)
349              mrevision = metaObj.get('revision','0.0.0')
350              if mrevision < filemrevision:
351                action = 'refresh'
352              elif mrevision > filemrevision:
353                action = 'conflict'
354            else:
355              action = 'add'
356          if action:
357            l.append({'action':action,'error_message':error_message,'filepath':filepath,'mrevision':mrevision,'filemrevision':filemrevision,'meta_type':self.meta_type})
358      # Deleted resources.
359      for id in self.getMetaobjIds():
360        metaObj = self.getMetaobj(id)
361        if not metaObj.get('acquired'):
362          if metaObj.get('package') == '' or metaObj.get('type') == 'ZMSPackage':
363            filename = id+suffix
364            filepath = path+'/'+filename
365            # Execute action.
366            if filepath in ids or '*' in ids:
367              self.delMetaobj(id)
368            elif not os.path.exists( filepath):
369              action = 'delete'
370              mrevision = metaObj['revision']
371              filemrevision = None
372              l.append({'action':action,'filepath':filepath,'mrevision':mrevision,'filemrevision':filemrevision,'meta_type':self.meta_type})
373     
374      return l
375
376
377    ############################################################################
378    #
379    #   OBJECTS
380    #
381    ############################################################################
382
383    # --------------------------------------------------------------------------
384    #  ZMSMetaobjManager.getTemplateId
385    #
386    #  Returns template-id for meta-object specified by given Id.
387    #  @deprecated
388    # --------------------------------------------------------------------------
389    def getTemplateId(self, id):
390      return "bodyContentZMSCustom_%s"%id
391
392    # --------------------------------------------------------------------------
393    #  ZMSMetaobjManager.renderTemplate
394    #
395    #  Renders template for meta-object.
396    # --------------------------------------------------------------------------
397    def renderTemplate(self, obj):
398      v = ""
399      id = obj.meta_id
400      tmpltIds = []
401      if obj.REQUEST.get("ZMS_SKIN") is not None and  obj.REQUEST.get("ZMS_EXT") is not None:
402        tmpltIds.append("%s_%s"%(obj.REQUEST.get("ZMS_SKIN"),obj.REQUEST.get("ZMS_EXT")))
403      tmpltIds.append("standard_html")
404      tmpltIds.append("bodyContentZMSCustom_%s"%id)
405      for tmpltId in tmpltIds:
406        if tmpltId in obj.getMetaobjAttrIds(id):
407          if obj.getMetaobjAttr(id,tmpltId)['type'] in ['method','py','zpt']:
408            v = obj.attr(tmpltId)
409            break
410          elif tmpltId not in ["standard_html"]:
411            tmpltDtml = getattr(obj,tmpltId,None)
412            if tmpltDtml is not None:
413              v = tmpltDtml(obj,obj.REQUEST)
414              try:
415                v = v.encode('utf-8')
416              except UnicodeDecodeError:
417                v = str(v)
418              break
419      return v
420
421
422    # --------------------------------------------------------------------------
423    #  ZMSMetaobjManager.__get_metaobjs__:
424    #
425    #  Returns all meta-objects (including acquisitions).
426    # --------------------------------------------------------------------------
427    def __get_metaobjs__(self):
428     
429      #-- [ReqBuff]: Fetch buffered value from Http-Request.
430      reqBuffId = '__get_metaobjs__'
431      try:
432        forced = \
433          not self.REQUEST.get( '__get_metaobjs__', False) and \
434          not self.REQUEST.get( 'recurse_updateVersionBuild', False)
435        obs = self.fetchReqBuff( reqBuffId, self.REQUEST, forced)
436        return obs
437      except:
438        obs = {}
439        raw = self.model
440        master_obs = None
441        for ob_id in raw.keys():
442          ob = raw.get(ob_id)
443          # Acquire from parent.
444          if ob.get('acquired',0) == 1:
445            acquired = 1
446            subobjects = ob.get('subobjects',1)
447            if master_obs is None:
448              portalMaster = self.getPortalMaster()
449              if portalMaster is not None:
450                master_obs = portalMaster.metaobj_manager.__get_metaobjs__()
451            if master_obs is not None:
452              if master_obs.has_key(ob_id):
453                ob = master_obs[ob_id].copy()
454              else:
455                ob = {'id':ob_id,'type':'ZMSUnknown'}
456              ob['acquired'] = acquired
457              ob['subobjects'] = subobjects
458              obs[ob_id] =  ob
459              if ob['type'] == 'ZMSPackage' and ob['subobjects'] == 1:
460                package = ob_id
461                for ob_id in master_obs.keys():
462                  ob = master_obs[ob_id].copy()
463                  if ob.get( 'package') == package:
464                    ob['acquired'] = 1
465                    obs[ob_id] =  ob
466          else:
467            obs[ob_id] = ob
468       
469        #-- [ReqBuff]: Returns value and stores it in buffer of Http-Request.
470        return self.storeReqBuff( reqBuffId, obs, self.REQUEST)
471
472
473    # --------------------------------------------------------------------------
474    #  ZMSMetaobjManager.__get_metaobj__:
475    #
476    #  Returns meta-object identified by id.
477    # --------------------------------------------------------------------------
478    def __get_metaobj__(self, id):
479      obs = self.__get_metaobjs__()
480      ob = obs.get( id)
481      return ob
482
483
484    # --------------------------------------------------------------------------
485    #  ZMSMetaobjManager.__is_page_container__:
486    # --------------------------------------------------------------------------
487    def __is_page_container__(self, id):
488     
489      #-- [ReqBuff]: Fetch buffered value from Http-Request.
490      reqBuffId = '__%s_is_page_container__'%id
491      try:
492        forced = True
493        return self.fetchReqBuff( reqBuffId, self.REQUEST, forced)
494      except:
495        rtnVal = False
496        ob = self.__get_metaobj__( id)
497        if type( ob) is dict and (ob.get('type') == 'ZMSDocument' or ob.get('id') == 'ZMSTeaserContainer'):
498          ids = map( lambda x: x['id'], filter( lambda x: x['type']=='*', ob['attrs']))
499          rtnVal = ids == ['e']
500       
501        #-- [ReqBuff]: Returns value and stores it in buffer of Http-Request.
502        return self.storeReqBuff( reqBuffId, rtnVal, self.REQUEST)
503
504
505    # --------------------------------------------------------------------------
506    #  ZMSMetaobjManager.getMetaobjIds:
507    #
508    #  Returns list of all meta-ids in model.
509    # --------------------------------------------------------------------------
510    def getMetaobjIds(self, sort=1, excl_ids=[]):
511      obs = self.__get_metaobjs__()
512      ids = obs.keys()
513      if len( excl_ids) > 0:
514        excl_types = [ 'ZMSPackage']
515        ids = filter( lambda x: x not in excl_ids and obs[x]['type'] not in excl_types, ids)
516      if sort:
517        mapping = map(lambda x: (self.display_type(self.REQUEST,x),x),ids)
518        mapping.sort()
519        ids = map(lambda x: x[1],mapping)
520      return ids
521
522
523    # --------------------------------------------------------------------------
524    #  ZMSMetaobjManager.getMetaobj:
525    #
526    #  Returns meta-object specified by id.
527    # --------------------------------------------------------------------------
528    def getMetaobj(self, id):
529      return _globals.nvl( self.__get_metaobj__(id), {'id':id, 'attrs':[], })
530
531
532    # --------------------------------------------------------------------------
533    #  ZMSMetaobjManager.getMetaobjId:
534    #
535    #  Returns id of meta-object specified by name.
536    # --------------------------------------------------------------------------
537    def getMetaobjId(self, name):
538      for id in self.getMetaobjIds():
539        if name == self.display_type(meta_type=id):
540          return id
541      return None
542
543
544    # --------------------------------------------------------------------------
545    #  ZMSMetaobjManager.setMetaobj:
546    #
547    #  Sets meta-object with specified values.
548    # --------------------------------------------------------------------------
549    def setMetaobj(self, ob):
550      obs = self.model
551      ob = ob.copy()
552      ob[ 'name'] = ob.get( 'name', '')
553      ob[ 'revision'] = ob.get( 'revision', '0.0.0')
554      ob[ 'type'] = ob.get( 'type', '')
555      ob[ 'package'] = ob.get( 'package', '')
556      ob[ 'attrs'] = ob.get( 'attrs', ob.get( '__obj_attrs__', []))
557      ob[ 'acquired'] = ob.get( 'acquired' ,0)
558      ob[ 'enabled'] = ob.get( 'enabled', 1)
559      ob[ 'zms_system'] = ob.get( 'zms_system', 0)
560      if ob.has_key('__obj_attrs__'):
561        del ob['__obj_attrs__']
562      obs[ob['id']] = ob
563      # Make persistent.
564      self.model = self.model.copy()
565
566
567    # --------------------------------------------------------------------------
568    #  ZMSMetaobjManager.acquireMetaobj:
569    #
570    #  Acquires meta-object specified by id.
571    # --------------------------------------------------------------------------
572    def acquireMetaobj(self, id, subobjects=1):
573      obs = self.model
574      ob = self.getMetaobj( id)
575      if ob is not None and len( ob.keys()) > 0 and subobjects == 1:
576        if ob.get('type','') == 'ZMSPackage':
577          pk_obs = filter( lambda x: x.get('package') == id, obs.values())
578          pk_ids = map( lambda x: x['id'], pk_obs)
579          for pk_id in pk_ids:
580            self.delMetaobj( pk_id)
581        self.delMetaobj( id)
582      ob = {}
583      ob['id'] = id
584      ob['acquired'] = 1
585      ob['subobjects'] = subobjects
586      self.setMetaobj( ob)
587      # Make persistent.
588      self.model = self.model.copy()
589
590
591    # --------------------------------------------------------------------------
592    #  ZMSMetaobjManager.delMetaobj:
593    #
594    #  Delete meta-object specified by id.
595    # --------------------------------------------------------------------------
596    def delMetaobj(self, id):
597      # Handle type.
598      ids = filter( lambda x: x.startswith(id+'.'), self.objectIds())
599      if ids:
600        self.manage_delObjects( ids)
601      # Delete object.
602      cp = self.model
603      obs = {}
604      for key in cp.keys():
605        if key == id:
606          # Delete attributes.
607          attr_ids = map( lambda x: x['id'], cp[key]['attrs'] )
608          for attr_id in attr_ids:
609            self.delMetaobjAttr( id, attr_id)
610        else:
611          obs[key] = cp[key]
612      # Make persistent.
613      self.model = obs.copy()
614
615
616    ############################################################################
617    #
618    #   ATTRIBUTES
619    #
620    ############################################################################
621
622    # --------------------------------------------------------------------------
623    #  ZMSMetaobjManager.notifyMetaobjAttrAboutValue:
624    #
625    #  Notify attribute for meta-object specified by attribute-id about value.
626    # --------------------------------------------------------------------------
627    def notifyMetaobjAttrAboutValue(self, meta_id, key, value):
628      sync_id = False
629     
630      attr = self.getMetaobjAttr( meta_id, key)
631      if attr is not None:
632        # Self-learning auto-complete attributes.
633        if attr.get('type') in ['autocomplete','multiautocomplete']:
634          keys = attr['keys']
635          if ''.join(keys).find('<dtml') < 0:
636            if type(value) is not list:
637              value = [value]
638            for v in value:
639              if v not in keys:
640                keys.append(v)
641                sync_id = meta_id
642            if sync_id:
643              self.setMetaobjAttr( meta_id, key, key, attr['name'], attr['mandatory'], attr['multilang'], attr['repetitive'], attr['type'], keys, attr['custom'], attr['default'])
644     
645      ##### SYNCHRONIZE ####
646      if sync_id:
647        self.synchronizeObjAttrs( sync_id)
648
649
650    # --------------------------------------------------------------------------
651    #  ZMSMetaobjManager.getMetaobjAttrIdentifierId:
652    #
653    #  Get attribute-id of identifier for datatable specified by meta-id.
654    # --------------------------------------------------------------------------
655    def getMetaobjAttrIdentifierId(self, meta_id):
656      for attr_id in self.getMetaobjAttrIds( meta_id, types=[ 'identifier', 'string', 'int']):
657        return attr_id
658      return None
659
660
661    # --------------------------------------------------------------------------
662    #  ZMSMetaobjManager.getMetaobjAttrIds:
663    #
664    #  Returns list of attribute-ids for meta-object specified by meta-id.
665    # --------------------------------------------------------------------------
666    def getMetaobjAttrIds(self, meta_id, types=[]):
667      return map(lambda x: x['id'], self.getMetaobjAttrs( meta_id, types))
668
669
670    # --------------------------------------------------------------------------
671    #  ZMSMetaobjManager.getMetaobjAttrs:
672    #
673    #  Returns list of attribute-ids for meta-object specified by meta-id.
674    # --------------------------------------------------------------------------
675    def getMetaobjAttrs(self, meta_id, types=[]):
676      attrs = []
677      ob = self.__get_metaobj__(meta_id)
678      if ob is not None:
679        attrs = ob.get('attrs',ob.get('__obj_attrs__'))
680        if attrs is None:
681          raise zExceptions.InternalError('Can\'t getMetaobjAttrIds: %s'%(str(meta_id)))
682        if len( types) > 0:
683          attrs = filter( lambda x: x['type'] in types, attrs)
684      return attrs
685
686
687    # --------------------------------------------------------------------------
688    #  ZMSMetaobjManager.getMetaobjAttr:
689    #
690    #  Get attribute for meta-object specified by attribute-id.
691    # --------------------------------------------------------------------------
692    def getMetaobjAttr(self, meta_id, key, sync=True):
693      meta_objs = self.__get_metaobjs__()
694      if meta_objs.get(meta_id,{}).get('acquired',0) == 1:
695        portalMaster = self.getPortalMaster()
696        if portalMaster is not None:
697          attr = portalMaster.getMetaobjAttr( meta_id, key)
698          return attr
699      meta_obj = meta_objs.get(meta_id,{})
700      attrs = meta_obj.get('attrs',meta_obj.get('__obj_attrs__'))
701      if attrs is None:
702        if meta_id == 'ZMSTrashcan':
703          return {}
704        raise zExceptions.InternalError('Can\'t getMetaobjAttr %s.%s'%(str(meta_id),str(key)))
705      for attr in attrs:
706        if key == attr['type']:
707          meta_attrs = self.getMetadictAttrs()
708          if key in meta_attrs:
709            attr_meta_type = attr['type']
710            attr = self.getMetadictAttr( attr_meta_type).copy()
711            attr['meta_type'] = attr_meta_type
712            return attr
713        if key == attr['id']:
714          attr = attr.copy()
715          attr['datatype_key'] = _globals.datatype_key(attr['type'])
716          attr['mandatory'] = attr.get('mandatory',0)
717          attr['multilang'] = attr.get('multilang',1)
718          attr['errors'] = attr.get('errors','')
719          meta_types = meta_objs.keys()
720          valid_types = self.valid_datatypes+self.valid_zopetypes+meta_types+['*']
721          # type is valid: sync type (copy might have been edited directly in ZODB via FTP!)
722          if sync and attr['type'] in valid_types:
723            attr['meta_type'] = ''
724            syncType( self, meta_id, attr)
725          # type not found: may be meta-attribute (must be '?' to display error on customize-form!)
726          else:
727            attr['meta_type'] = '?'
728          return attr
729      return None
730
731
732    # --------------------------------------------------------------------------
733    #  ZMSMetaobjManager.setMetaobjAttr:
734    #
735    #  Set/add meta-object attribute with specified values.
736    # --------------------------------------------------------------------------
737    def setMetaobjAttr(self, id, oldId, newId, newName='', newMandatory=0, newMultilang=1, newRepetitive=0, newType='string', newKeys=[], newCustom='', newDefault='', zms_system=0):
738      ob = self.__get_metaobj__(id)
739      if ob is None: return
740      attrs = copy.copy(ob['attrs'])
741     
742      # Set Attributes.
743      if newType in ['delimiter','hint','interface']:
744        newCustom = ''
745      if newType in ['resource'] and (type(newCustom) is str or type(newCustom) is int):
746        newCustom = None
747      if newType not in ['*','autocomplete','multiautocomplete','multiselect','recordset','select']:
748        newKeys = []
749      if newType in self.getMetaobjIds(sort=0)+['*']:
750        newMultilang = 0
751     
752      # Defaults for Insert
753      method_types = [ 'method','py','zpt'] + self.valid_zopetypes
754      if oldId is None and \
755         newType in method_types and \
756         (newCustom == '' or type(newCustom) is not str):
757        if newType in [ 'method', 'DTML Method', 'DTML Document']:
758          newCustom = ''
759          newCustom += '<dtml-comment>--// BO '+ newId + ' //--</dtml-comment>\n'
760          newCustom += '\n'
761          newCustom += '<dtml-comment>--// EO '+ newId + ' //--</dtml-comment>\n'
762        elif newType in [ 'External Method']:
763          newCustom = ''
764          newCustom += '# Example code:\n'
765          newCustom += '\n'
766          newCustom += 'def ' + newId + '( self):\n'
767          newCustom += '  return "This is the external method ' + newId + '"\n'
768        elif newType in [ 'zpt', 'Page Template']:
769          newCustom = ''
770          newCustom += '<span tal:replace="here/title_or_id">content title or id</span>'
771          newCustom += '<span tal:condition="template/title" tal:replace="template/title">optional template title</span>'
772        elif newType in [ 'py', 'Script (Python)']:
773          newCustom = '## Script (Python) ""\n'
774          newCustom += '##bind container=container\n'
775          newCustom += '##bind context=context\n'
776          newCustom += '##bind namespace=\n'
777          newCustom += '##bind script=script\n'
778          newCustom += '##bind subpath=traverse_subpath\n'
779          newCustom += '##parameters='
780          if newType in ['py']: newCustom += 'zmscontext=None'
781          newCustom += '\n'
782          newCustom += '##title='
783          if newType in ['py']: newCustom += newType+': '
784          newCustom += newName
785          newCustom += '\n'
786          newCustom += '##\n'
787          newCustom += '# --// BO '+ newId + ' //--\n'
788          newCustom += '# Example code:\n'
789          newCustom += '\n'
790          newCustom += '# Import a standard function, and get the HTML request and response objects.\n'
791          newCustom += 'from Products.PythonScripts.standard import html_quote\n'
792          newCustom += 'request = container.REQUEST\n'
793          newCustom += 'RESPONSE =  request.RESPONSE\n'
794          newCustom += '\n'
795          newCustom += '# Return a string identifying this script.\n'
796          newCustom += 'print "This is the", script.meta_type, \'"%s"\' % script.getId(),\n'
797          newCustom += 'if script.title:\n'
798          newCustom += '    print "(%s)" % html_quote(script.title),\n'
799          newCustom += 'print "in", container.absolute_url()\n'
800          newCustom += 'return printed\n'
801          newCustom += '\n'
802          newCustom += '# --// EO '+ newId + ' //--\n'
803        elif newType in [ 'Z SQL Method']:
804          newCustom = ''
805          newCustom += '<connection>%s</connection>\n'%self.SQLConnectionIDs()[0][0]
806          newCustom += '<params></params>\n'
807          newCustom += 'SELECT * FROM tablename\n'
808     
809      # Handle resources.
810      if (newType in ['resource']) or \
811         (newMandatory and newType in self.getMetaobjIds()) or \
812         (newRepetitive and newType in self.getMetaobjIds()):
813        if not newCustom:
814          if oldId is not None and id+'.'+oldId in self.objectIds():
815            self.manage_delObjects(ids=[id+'.'+oldId])
816        elif isinstance( newCustom, _blobfields.MyFile):
817          if oldId is not None and id+'.'+oldId in self.objectIds():
818            self.manage_delObjects(ids=[id+'.'+oldId])
819          self.manage_addFile( id=id+'.'+newId, file=newCustom.getData(),title=newCustom.getFilename(),content_type=newCustom.getContentType())
820        elif oldId is not None and oldId != newId and id+'.'+oldId in self.objectIds():
821          self.manage_renameObject(id=id+'.'+oldId,new_id=id+'.'+newId)
822        newCustom = ''
823     
824      attr = {}
825      attr['id'] = newId
826      attr['name'] = newName
827      attr['mandatory'] = newMandatory
828      attr['multilang'] = newMultilang
829      attr['repetitive'] = newRepetitive
830      attr['type'] = newType
831      attr['keys'] = newKeys
832      attr['custom'] = newCustom
833      attr['default'] = newDefault
834     
835      # Parse Dtml for Errors.
836      newOb = None
837      message = ''
838      dtml = ''
839      if newType in [ 'delimiter', 'hint', 'interface']:
840        dtml = newName
841      elif newType in [ 'method', 'DTML Method', 'DTML Document']:
842        dtml = newCustom
843      if len(dtml) > 0:
844        message = _globals.dt_parse( self, dtml)
845        if len( message) > 0:
846          attr['errors'] = message
847          message = '<div class="ui-state-error ui-corner-all">DTML-Error in '+newId+'<br>'+message+'</div>'
848        else:
849          # Handle methods.
850          if newType == 'method':
851            if oldId is not None and id+'.'+oldId in self.objectIds():
852              self.manage_delObjects(ids=[id+'.'+oldId])
853            self.manage_addDTMLMethod( id+'.'+newId, newType+': '+newName, newCustom)
854            newOb = getattr( self, id+'.'+newId)
855          # Handle interfaces.
856          elif newType == 'interface':
857            if oldId is not None and id+'.'+oldId in self.objectIds():
858              self.manage_delObjects(ids=[id+'.'+oldId])
859            self.manage_addDTMLMethod( id+'.'+newId, newType, newName)
860      # Handle py.
861      if newType == 'py':
862        if oldId is not None and id+'.'+oldId in self.objectIds():
863          self.manage_delObjects(ids=[id+'.'+oldId])
864        PythonScript.manage_addPythonScript( self, id+'.'+newId)
865        newOb = getattr(self,id+'.'+newId)
866        newOb.write(newCustom)
867      # Handle zpt.
868      elif newType == 'zpt':
869        if oldId is not None and id+'.'+oldId in self.objectIds():
870          self.manage_delObjects(ids=[id+'.'+oldId])
871        ZopePageTemplate.manage_addPageTemplate( self, id+'.'+newId, title=newType+': '+newName, text=newCustom)
872        newOb = getattr(self,id+'.'+newId)
873        newOb.output_encoding = 'utf-8'
874     
875      # Restrict access.
876      if newOb is not None:
877        newOb.manage_acquiredPermissions([])
878        permissions = map(lambda x: x['name'],newOb.permissionsOfRole('Manager'))
879        for role_to_manage in [ 'ZMSAuthor', 'ZMSEditor', 'ZMSAdministrator']:
880          newOb.manage_role(role_to_manage=role_to_manage,permissions=permissions)
881     
882      # Replace
883      ids = map( lambda x: x['id'], attrs) # self.getMetaobjAttrIds(id)
884      if oldId in ids:
885        i = ids.index(oldId)
886        attrs[i] = attr
887      else:
888        # Always append new methods at the end.
889        if oldId == newId or newType in method_types:
890          attrs.append( attr)
891        # Insert new attributes before methods
892        else:
893          i = len( attrs)
894          while i > 0 and attrs[ i - 1][ 'type'] in method_types:
895            i -= 1
896          if i < len(attrs):
897            attrs.insert( i, attr)
898          else:
899            attrs.append( attr)
900      ob['attrs'] = attrs
901     
902      # Handle native Zope-Objects.
903      if newType in self.valid_zopetypes:
904        # Get container.
905        container = self.getHome()
906        for ob_id in newId.split('/')[:-1]:
907          if ob_id not in container.objectIds():
908            container.manage_addFolder(id=ob_id,title='Folder: %s'%id)
909          container = getattr( container, ob_id)
910        newObId = newId.split('/')[-1]
911        # Get container (old).
912        if oldId is not None:
913          oldContainer = self.getHome()
914          for ob_id in oldId.split('/')[:-1]:
915            oldContainer = getattr(oldContainer,ob_id,None)
916          oldObId = oldId.split('/')[-1]
917        # External Method.
918        if newType == 'External Method':
919          try:
920            _fileutil.remove( INSTANCE_HOME+'/Extensions/'+oldObId+'.py')
921          except:
922            pass
923          newExternalMethod = INSTANCE_HOME+'/Extensions/'+newObId+'.py'
924          _fileutil.exportObj( newCustom, newExternalMethod)
925        # Insert Zope-Object.
926        if oldId is None or oldId == newId:
927          # Delete existing Zope-Object.
928          if newObId in container.objectIds():
929            if newType in ['External Method', 'Page Template'] or \
930               newType not in self.valid_zopetypes:
931              container.manage_delObjects( ids=[ newObId])
932            # Delete old Zope-Object if type is incompatible.
933            if newObId in container.objectIds() and getattr(container,newObId).meta_type != newType:
934              container.manage_delObjects( ids=[ newObId])
935          # Add new Zope-Object.
936          if newObId not in container.objectIds():
937            if newType == 'DTML Method':
938              container.manage_addDTMLMethod( newObId, newName, newCustom)
939            elif newType == 'DTML Document':
940              container.manage_addDTMLDocument( newObId, newName, newCustom)
941            elif newType == 'External Method':
942              ExternalMethod.manage_addExternalMethod( container, newObId, newName, newId, newId)
943            elif newType == 'Folder':
944              container.manage_addFolder(id=newObId,title=newName)
945            elif newType == 'Page Template':
946              ZopePageTemplate.manage_addPageTemplate( container, newObId, title=newName, text=newCustom)
947              newOb = getattr( container, newObId)
948              newOb.output_encoding = 'utf-8'
949            elif newType == 'Script (Python)':
950              PythonScript.manage_addPythonScript( container, newObId)
951            elif newType == 'Z SQL Method':
952              try:
953                from Products.ZSQLMethods import SQL
954                connection_id = self.SQLConnectionIDs()[0][0]
955                arguments = ''
956                template = ''
957                SQL.manage_addZSQLMethod( container, newObId, newName, connection_id, arguments, template)
958              except:
959                pass
960        # Rename Zope-Object.
961        elif oldId != newId:
962          if oldContainer != container:
963            cb_copy_data = oldContainer.manage_cutObjects( ids=[oldObId])
964            container.manage_pasteObjects( cb_copy_data)
965          if oldObId != newObId:
966            container.manage_renameObject( id=oldObId, new_id=newObId)
967        # Change Zope-Object.
968        newOb = getattr( container, newObId)
969        if newType in [ 'DTML Method', 'DTML Document']:
970          newOb.manage_edit( title=newName, data=newCustom)
971          roles=[ 'Manager']
972          newOb._proxy_roles=tuple(roles)
973          if newId.find( 'manage_') >= 0:
974            newOb.manage_role(role_to_manage='Authenticated',permissions=['View'])
975            newOb.manage_acquiredPermissions([])
976        elif newType == 'Folder':
977          if isinstance( newCustom, _blobfields.MyFile) and len(newCustom.filename) > 0:
978            newOb.manage_delObjects(ids=newOb.objectIds())
979            _ziputil.importZip2Zodb( newOb, newCustom.getData())
980          attr['custom'] = ''
981        elif newType == 'Script (Python)':
982          newOb.write(newCustom)
983          roles=[ 'Manager']
984          newOb._proxy_roles=tuple(roles)
985          if newId.find( 'manage_') >= 0:
986            newOb.manage_role(role_to_manage='Authenticated',permissions=['View'])
987            newOb.manage_acquiredPermissions([])
988        elif newType == 'Z SQL Method':
989          connection = newCustom
990          connection = connection[connection.find('<connection>'):connection.find('</connection>')]
991          connection = connection[connection.find('>')+1:]
992          arguments = newCustom
993          arguments = arguments[arguments.find('<params>'):arguments.find('</params>')]
994          arguments = arguments[arguments.find('>')+1:]
995          template = newCustom
996          template = template[template.find('</params>'):]
997          template = template[template.find('>')+1:]
998          template = '\n'.join(filter( lambda x: len(x) > 0, template.split('\n')))
999          newOb.manage_edit(title=newName,connection_id=connection,arguments=arguments,template=template)
1000     
1001      # Assign Attributes to Meta-Object.
1002      ob['zms_system'] = int( ob['zms_system'] and (oldId is None or zms_system))
1003      self.model[id] = ob
1004     
1005      # Make persistent.
1006      self.model = self.model.copy()
1007     
1008      # Return with message.
1009      return message
1010
1011
1012    # --------------------------------------------------------------------------
1013    #  ZMSMetaobjManager.delMetaobjAttr:
1014    #
1015    #  Delete attribute from meta-object specified by id.
1016    # --------------------------------------------------------------------------
1017    def delMetaobjAttr(self, id, attr_id):
1018      ob = self.__get_metaobj__(id)
1019      attrs = copy.copy(ob['attrs'])
1020     
1021      # Delete Attribute.
1022      cp = []
1023      for attr in attrs:
1024        if attr['id'] == attr_id:
1025          if id+'.'+attr['id'] in self.objectIds():
1026            self.manage_delObjects(ids=[id+'.'+attr['id']])
1027          if attr['type'] in self.valid_zopetypes:
1028            # Get container.
1029            container = self.getHome()
1030            for ob_id in attr['id'].split('/')[:-1]:
1031              container = getattr( container, ob_id)
1032            ob_id = attr['id'].split('/')[-1]
1033            if ob_id in container.objectIds([attr['type']]):
1034              container.manage_delObjects(ids=[ob_id])
1035            if attr['type'] == 'External Method':
1036              try:
1037                _fileutil.remove( INSTANCE_HOME+'/Extensions/'+ob_id+'.py')
1038              except:
1039                pass
1040        else:
1041          cp.append(attr)
1042      ob['attrs'] = cp
1043     
1044      # Assign Attributes to Meta-Object.
1045      ob['zms_system'] = 0
1046      self.model[id] = ob
1047     
1048      # Make persistent.
1049      self.model = self.model.copy()
1050
1051
1052    # --------------------------------------------------------------------------
1053    #  ZMSMetaobjManager.moveMetaobjAttr:
1054    #
1055    #  Move meta-object attribute to specified position.
1056    # --------------------------------------------------------------------------
1057    def moveMetaobjAttr(self, id, attr_id, pos):
1058      ob = self.__get_metaobj__(id)
1059      attrs = copy.copy(ob['attrs'])
1060      # Move Attribute.
1061      ids = self.getMetaobjAttrIds(id)
1062      i = ids.index(attr_id)
1063      attr = attrs[i]
1064      attrs.remove(attr)
1065      attrs.insert(pos,attr)
1066      ob['attrs'] = attrs
1067      # Assign Attributes to Meta-Object.
1068      self.model[id] = ob
1069      # Make persistent.
1070      self.model = self.model.copy()
1071
1072
1073    ############################################################################
1074    #  ZMSMetaobjManager.manage_ajaxChangeProperties:
1075    #
1076    #  Change properties.
1077    ############################################################################
1078    def manage_ajaxChangeProperties(self, id, REQUEST=None, RESPONSE=None):
1079      """ MetaobjManager.manage_ajaxChangeProperties """
1080      ob = self.__get_metaobj__(id)
1081      RESPONSE = REQUEST.RESPONSE
1082      content_type = 'text/xml; charset=utf-8'
1083      filename = 'manage_ajaxChangeProperties.xml'
1084      RESPONSE.setHeader('Content-Type',content_type)
1085      RESPONSE.setHeader('Content-Disposition','inline;filename="%s"'%filename)
1086      RESPONSE.setHeader('Cache-Control', 'no-cache')
1087      RESPONSE.setHeader('Pragma', 'no-cache')
1088      xml = self.getXmlHeader()
1089      xml += '<result '
1090      xml += ' id="%s"'%id
1091      for key in REQUEST.form.keys():
1092        if key.find('set') == 0:
1093          k = key[3:].lower()
1094          v = REQUEST.form.get(key)
1095          if k in ob.keys():
1096            ob[k] = v
1097            xml += ' %s="%s"'%(k,str(v))
1098      xml += '/>'
1099      # Assign Attributes to Meta-Object.
1100      self.model[id] = ob
1101      # Make persistent.
1102      self.model = self.model.copy()
1103      return xml
1104
1105
1106    ############################################################################
1107    #  ZMSMetaobjManager.manage_changeProperties:
1108    #
1109    #  Change properties.
1110    ############################################################################
1111    def manage_changeProperties(self, lang, btn='', key='all', REQUEST=None, RESPONSE=None):
1112        """ ZMSMetaobjManager.manage_changeProperties """
1113        old_model = copy.deepcopy(self.model)
1114        message = ''
1115        extra = {}
1116        t0 = time.time()
1117        id = REQUEST.get('id','').strip()
1118        target = 'manage_main'
1119        REQUEST.set( '__get_metaobjs__', True)
1120       
1121        try:
1122         
1123          # Delete.
1124          # -------
1125          # Delete Object.
1126          if key == 'obj' and btn == self.getZMILangStr('BTN_DELETE'):
1127            ids = [id]
1128            metaObj = self.getMetaobj( id)
1129            if metaObj['type'] == 'ZMSPackage':
1130              for pkgMetaObjId in self.getMetaobjIds():
1131                pkgMetaObj = self.getMetaobj( pkgMetaObjId)
1132                if pkgMetaObj[ 'package'] == metaObj[ 'id']:
1133                    ids.insert( 0, pkgMetaObjId)
1134            metaobj = findMetaobj( self, ids)
1135            if metaobj is None:
1136              for id in ids:
1137                self.delMetaobj( id)
1138              id = ''
1139              message = self.getZMILangStr('MSG_CHANGED')
1140            else:
1141              raise zExceptions.Forbidden('All instances of "%s" must be deleted before definition can be deleted: <a href="%s/manage_main#_%s">%s</a>!'%(id,metaobj.getParentNode().absolute_url(),metaobj.id,metaobj.absolute_url()))
1142          # Delete Attribute.
1143          elif key == 'attr' and btn == 'delete':
1144            attr_id = REQUEST['attr_id']
1145            self.delMetaobjAttr( id, attr_id)
1146         
1147          # Change.
1148          # -------
1149          elif key == 'all' and btn == self.getZMILangStr('BTN_SAVE'):
1150            savedAttrs = copy.copy(self.getMetaobj(id)['attrs'])
1151            # Change Object.
1152            newValue = {}
1153            newValue['id'] = id
1154            newValue['name'] = REQUEST.get('obj_name').strip()
1155            newValue['revision'] = REQUEST.get('obj_revision').strip()
1156            newValue['type'] = REQUEST.get('obj_type').strip()
1157            newValue['package'] = REQUEST.get('obj_package').strip()
1158            newValue['attrs'] = savedAttrs
1159            newValue['enabled'] = REQUEST.get('obj_enabled',0)
1160            newValue['access'] = {
1161             'insert': REQUEST.get( 'access_insert', []),
1162             'insert_custom': REQUEST.get( 'access_insert_custom', ''),
1163             'delete': REQUEST.get( 'access_delete', []),
1164             'delete_custom': REQUEST.get( 'access_delete_custom', ''),
1165            }
1166            self.setMetaobj( newValue)
1167            # Change Attributes.
1168            for old_id in REQUEST.get('old_ids',[]):
1169              attr_id = REQUEST['attr_id_%s'%old_id].strip()
1170              newName = REQUEST['attr_name_%s'%old_id].strip()
1171              newMandatory = REQUEST.get( 'attr_mandatory_%s'%old_id, 0)
1172              newMultilang = REQUEST.get( 'attr_multilang_%s'%old_id, 0)
1173              newRepetitive = REQUEST.get( 'attr_repetitive_%s'%old_id, 0)
1174              newType = REQUEST.get( 'attr_type_%s'%old_id)
1175              newMetaType = REQUEST.get( 'attr_meta_type_%s'%old_id, '')
1176              newKeys = self.string_list(REQUEST.get('attr_keys_%s'%old_id,''),'\n')
1177              newCustom = REQUEST.get('attr_custom_%s'%old_id,'')
1178              newDefault = REQUEST.get('attr_default_%s'%old_id,'')
1179              if isinstance(newCustom,ZPublisher.HTTPRequest.FileUpload):
1180                  if len(getattr(newCustom,'filename','')) > 0:
1181                      newCustom = _blobfields.createBlobField( self,_globals.DT_FILE, newCustom, mediadbStorable=False)
1182                  else:
1183                      REQUEST.set('attr_custom_%s_modified'%old_id,'0')
1184              if REQUEST.get('attr_custom_%s_modified'%old_id,'1') == '0' and \
1185                 REQUEST.get('attr_custom_%s_active'%old_id,'0') == '1':
1186                  savedAttr = filter(lambda x: x['id']==old_id, savedAttrs)[0]
1187                  syncType( self, id, savedAttr)
1188                  newCustom = savedAttr['custom']
1189              if len( newMetaType) > 0:
1190                  attr_id = old_id
1191                  newType = newMetaType
1192              message += self.setMetaobjAttr( id, old_id, attr_id, newName, newMandatory, newMultilang, newRepetitive, newType, newKeys, newCustom, newDefault)
1193            # Return with message.
1194            message += self.getZMILangStr('MSG_CHANGED')
1195          elif key == 'obj' and btn == self.getZMILangStr('BTN_SAVE'):
1196            # Change Acquired-Object.
1197            subobjects = REQUEST.get('obj_subobjects',0)
1198            self.acquireMetaobj( id, subobjects)
1199            # Return with message.
1200            message += self.getZMILangStr('MSG_CHANGED')
1201         
1202          # Copy.
1203          # -----
1204          elif btn == self.getZMILangStr('BTN_COPY'):
1205            metaOb = self.getMetaobj(id)
1206            if metaOb.get('acquired',0) == 1:
1207              xml = self.getPortalMaster().metaobj_manager.exportMetaobjXml([id])
1208              self.importMetaobjXml(xml=xml)
1209              message = self.getZMILangStr('MSG_IMPORTED')%('<em>%s</em>'%id)
1210         
1211          # Export.
1212          # -------
1213          elif btn == self.getZMILangStr('BTN_EXPORT'):
1214            ids = REQUEST.get('ids',[])
1215            return self.exportMetaobjXml(ids,REQUEST,RESPONSE)
1216         
1217          # Insert.
1218          # -------
1219          elif btn == self.getZMILangStr('BTN_INSERT'):
1220            # Insert Object.
1221            if key == 'obj':
1222              id = REQUEST['_meta_id'].strip()
1223              newValue = {}
1224              newValue['id'] = id
1225              newValue['name'] = REQUEST.get('_meta_name').strip()
1226              newValue['type'] = REQUEST.get('_meta_type').strip()
1227              self.setMetaobj( newValue)
1228              # Insert Attributes.
1229              if newValue['type'] == 'ZMSDocument':
1230                message += self.setMetaobjAttr(id,None,newId='titlealt',newType='titlealt')
1231                message += self.setMetaobjAttr(id,None,newId='title',newType='title')
1232              elif newValue['type'] == 'ZMSTeaserElement':
1233                message += self.setMetaobjAttr(id,None,newId='titlealt',newType='titlealt')
1234                message += self.setMetaobjAttr(id,None,'attr_penetrance',self.getZMILangStr('ATTR_PENETRANCE'),1,1,0,'select',['this','sub_nav','sub_all'])
1235              elif newValue['type'] == 'ZMSRecordSet':
1236                message += self.setMetaobjAttr(id,None,'records',self.getZMILangStr('ATTR_RECORDS'),1,1,0,'list')
1237                message += self.setMetaobjAttr(id,None,'col_id','COL_ID',1,0,0,'identifier',[],0)
1238                message += self.setMetaobjAttr(id,None,'col_1','COL_1',0,0,0,'string',[],1)
1239                message += self.setMetaobjAttr(id,None,'col_2','COL_2',0,0,0,'string',[],1)
1240              elif newValue['type'] == 'ZMSModule':
1241                message += self.setMetaobjAttr(id,None,'zexp','ZEXP',0,0,0,'resource')
1242              # Insert Template.
1243              if newValue['type'] not in [ 'ZMSModule', 'ZMSPackage']:
1244                tmpltId = 'standard_html'
1245                tmpltName = 'Template: %s'%newValue['name']
1246                tmpltCustom = []
1247                tmpltCustom.append('<!-- %s.%s -->\n'%(id,tmpltId))
1248                tmpltCustom.append('\n')
1249                tmpltCustom.append('<span tal:omit-tag="" tal:define="global\n')
1250                tmpltCustom.append('\t\tzmscontext options/zmscontext">\n')
1251                if newValue['type'] == 'ZMSRecordSet':
1252                  tmpltCustom.append('\t<h2 tal:content="python:zmscontext.getTitlealt(request)">The title.alt</h2>\n')
1253                  tmpltCustom.append('\t<p class="description" tal:content="python:\'%i %s\'%(len(zmscontext.attr(zmscontext.getMetaobj(zmscontext.meta_id)[\'attrs\'][0][\'id\'])),zmscontext.getLangStr(\'ATTR_RECORDS\',request[\'lang\']))">#N records</p>\n')
1254                tmpltCustom.append('</span>\n')
1255                tmpltCustom.append('\n')
1256                tmpltCustom.append('<!-- /%s.%s -->\n'%(id,tmpltId))
1257                tmpltCustom = ''.join(tmpltCustom)
1258                message += self.setMetaobjAttr(id,None,tmpltId,tmpltName,0,0,0,'zpt',[],tmpltCustom)
1259              message += self.getZMILangStr('MSG_INSERTED')%id
1260            # Insert Attribute.
1261            if key == 'attr':
1262              attr_id = REQUEST['attr_id'].strip()
1263              newName = REQUEST['attr_name'].strip()
1264              newMandatory = REQUEST.get('_mandatory',0)
1265              newMultilang = REQUEST.get('_multilang',0)
1266              newRepetitive = REQUEST.get('_repetitive',0)
1267              newType = REQUEST.get('_type','string')
1268              newKeys = REQUEST.get('_keys',[])
1269              newCustom = REQUEST.get('_custom','')
1270              newDefault = REQUEST.get('_default','')
1271              message += self.setMetaobjAttr( id, None, attr_id, newName, newMandatory, newMultilang, newRepetitive, newType, newKeys, newCustom, newDefault)
1272              message += self.getZMILangStr('MSG_INSERTED')%attr_id
1273         
1274          # Acquire.
1275          # --------
1276          elif btn == self.getZMILangStr('BTN_ACQUIRE'):
1277            immediately = REQUEST.get('immediately',0)
1278            overwrite = []
1279            ids = REQUEST.get('aq_ids',[])
1280            for id in ids:
1281              if not immediately and id in self.getMetaobjIds():
1282                overwrite.append( id)
1283              else:
1284                self.acquireMetaobj( id)
1285            if overwrite:
1286              id = ''
1287              extra['section'] = 'acquire'
1288              extra['temp_ids'] = ','.join(overwrite)
1289            else:
1290              # Return with message.
1291              message = self.getZMILangStr('MSG_INSERTED')%str(len(ids))
1292         
1293          # Import.
1294          # -------
1295          elif btn == self.getZMILangStr('BTN_IMPORT'):
1296            immediately = False
1297            xmlfile = None
1298            temp_folder = self.temp_folder
1299            temp_id = self.id + '_' + REQUEST['AUTHENTICATED_USER'].getId() + '.xml'
1300            if temp_id in temp_folder.objectIds():
1301              filename = str(getattr( temp_folder, temp_id).title)
1302              xmlfile = str(getattr( temp_folder, temp_id).data)
1303              zms_system = REQUEST.get('zms_system',0)
1304              temp_folder.manage_delObjects([temp_id])
1305              immediately = True
1306            if REQUEST.get('file'):
1307              f = REQUEST['file']
1308              filename = f.filename
1309              xmlfile = f
1310              zms_system = 0
1311            if REQUEST.get('init'):
1312              file = REQUEST['init']
1313              filename, xmlfile = self.getConfXmlFile( file)
1314              zms_system = 1
1315            if xmlfile is not None:
1316              if not immediately:
1317                xml = xmlfile.read()
1318                xmlfile = StringIO( xml)
1319                v = self.parseXmlString( xmlfile, mediadbStorable=False)
1320                xmlfile = StringIO( xml)
1321                immediately = not type( v) is list
1322              if not immediately:
1323                file = temp_folder.manage_addFile(id=temp_id,title=filename,file=xmlfile)
1324                extra['section'] = 'import'
1325                extra['temp_import_file_id'] = temp_id
1326                extra['temp_import_zms_system:int'] = zms_system
1327              else:
1328                createIdsFilter = REQUEST.get('createIdsFilter')
1329                self.importMetaobjXml(xmlfile,zms_system=zms_system,createIdsFilter=createIdsFilter)
1330                message = self.getZMILangStr('MSG_IMPORTED')%('<em>%s</em>'%filename)
1331         
1332          # Move to.
1333          # --------
1334          elif key == 'attr' and btn == 'move_to':
1335            pos = REQUEST['pos']
1336            attr_id = REQUEST['attr_id']
1337            self.moveMetaobjAttr( id, attr_id, pos)
1338            message = self.getZMILangStr('MSG_MOVEDOBJTOPOS')%(("<em>%s</em>"%attr_id),(pos+1))
1339         
1340          ##### SYNCHRONIZE ####
1341          sync_id = []
1342          for k in self.model.keys():
1343            if old_model.has_key(k):
1344              d = self.model[k]
1345              types = self.valid_types
1346              for i in range(len(self.metas)/2):
1347                  types.append(self.metas[i*2])
1348              valid_types_attrs = map(lambda x: (x['id'],x), filter(lambda x: x['type'] in self.valid_types, d.get('attrs',[])))
1349              valid_types_attrs.sort()
1350              old_d = old_model[k]
1351              old_valid_types_attrs = map(lambda x: (x['id'],x), filter(lambda x: x['type'] in self.valid_types, old_d.get('attrs',[])))
1352              old_valid_types_attrs.sort()
1353              if valid_types_attrs != old_valid_types_attrs:
1354                sync_id.append(k)
1355            else:
1356              sync_id.append(k)
1357          if sync_id:
1358            _globals.writeBlock( self, '[ZMSMetaobjManager.manage_changeProperties]: sync_id=%s'%str(sync_id))
1359            self.synchronizeObjAttrs( sync_id)
1360       
1361        # Handle exception.
1362        except:
1363          _globals.writeError(self,"[manage_changeProperties]")
1364          error = str( sys.exc_type)
1365          if sys.exc_value:
1366            error += ': ' + str( sys.exc_value)
1367          target = self.url_append_params( target, { 'manage_tabs_error_message':error})
1368       
1369        # Return with message.
1370        if RESPONSE:
1371          target = self.url_append_params( target, { 'lang':lang, 'id':id, 'attr_id':REQUEST.get('attr_id','')})
1372          target = self.url_append_params( target, extra)
1373          if len( message) > 0:
1374            message += ' (in '+str(int((time.time()-t0)*100.0)/100.0)+' secs.)'
1375            target = self.url_append_params( target, { 'manage_tabs_message':message})
1376          if REQUEST.has_key('inp_id_name'):
1377            target += '&inp_id_name=%s'%REQUEST.get('inp_id_name')
1378            target += '&inp_name_name=%s'%REQUEST.get('inp_name_name')
1379            target += '&inp_value_name=%s'%REQUEST.get('inp_value_name')
1380            target += '#Edit'
1381          return RESPONSE.redirect( target)
1382       
1383        return message
1384
1385################################################################################
Note: See TracBrowser for help on using the repository browser.