source: ZMS/trunk/_metacmdmanager.py @ 1702

Revision 1702, 18.1 KB checked in by zmsdev, 7 months ago (diff)

revised meta-command manager: added support for actions on multiple objects, added support for stereotypes

Line 
1################################################################################
2# _metacmdmanager.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 App.special_dtml import HTMLFile
21from Products.PythonScripts import PythonScript
22import copy
23import string
24import urllib
25# Product Imports.
26import _globals
27import _objattrs
28
29
30# Example code.
31# -------------
32
33dtmlMethodWithExecExampleCode = \
34  '<dtml-comment>\n' + \
35  '# Example code:\n' + \
36  '</dtml-comment>\n' + \
37  '\n' + \
38  '<dtml-call expr="REQUEST.set(\'message\',\'This is %s\'%meta_type)">\n' + \
39  '<dtml-return message>\n' + \
40  ''
41
42dtmlMethodWithoutExecExampleCode = \
43  '<dtml-comment>\n' + \
44  '# Example code:\n' + \
45  '</dtml-comment>\n' + \
46  '\n' + \
47  '<dtml-var manage_page_header>\n' + \
48  '<head>\n' + \
49  ' <title>$$NAME$$</title>\n' + \
50  '</head>\n' + \
51  '<dtml-var "manage_tabs(_,_,my_manage_options=[{\'label\':\'$$NAME$$\',\'action\':\'\'}])">\n' + \
52  '<dtml-var manage_page_header>\n' + \
53  ''
54
55pageTemplateExampleCode = \
56  ''
57
58pyScriptExampleCode = \
59  '# Example code:\n' + \
60  '\n' + \
61  '# Import a standard function, and get the HTML request and response objects.\n' + \
62  'from Products.PythonScripts.standard import html_quote\n' + \
63  'request = container.REQUEST\n' + \
64  'RESPONSE =  request.RESPONSE\n' + \
65  '\n' + \
66  '# Return a string identifying this script.\n' + \
67  'print "This is the", script.meta_type, \'"%s"\' % script.getId(),\n' + \
68  'if script.title:\n' + \
69  '    print "(%s)" % html_quote(script.title),\n' + \
70  'print "in", container.absolute_url()\n' + \
71  'return printed\n' + \
72  ''
73
74
75"""
76################################################################################
77#
78#   K E Y S
79#
80################################################################################
81"""
82
83CONF_METACMDS = "ZMS.custom.commands"
84
85
86"""
87################################################################################
88#
89#   X M L   I M / E X P O R T
90#
91################################################################################
92"""
93
94# ------------------------------------------------------------------------------
95#  _metacmdmanager.importXml
96# ------------------------------------------------------------------------------
97
98def _importXml(self, item, zms_system=0, createIfNotExists=1):
99
100  id = item['id']
101  metaCmds = getRawMetacmds(self)
102  metaCmds = filter(lambda x: x.get('zms_system',0)==1,metaCmds)
103  ids = map(lambda x: x['id'], metaCmds)
104  if createIfNotExists == 1 or id in ids:
105
106    # Delete existing object.
107    try: delMetacmd(self, id)
108    except: pass
109
110    # Initialize attributes of new object.
111    newId = id
112    newAcquired = 0
113    newName = item['name']
114    newMethod = item['meta_type']
115    newExec = item.has_key('exec') and item['exec']
116    newDescription = item['description']
117    newMetaTypes = item['meta_types']
118    newRoles = item['roles']
119    newCustom = item.get('custom','')
120    newNodes = item.get('nodes','{$}')
121    newData = item['data']
122
123    # Return with new id.
124    return setMetacmd(self, None, newId, newAcquired, newName, newMethod, \
125      newData, newExec, newDescription, newMetaTypes, newRoles, newCustom, \
126      newNodes, zms_system)
127
128
129def importXml(self, xml, REQUEST=None, zms_system=0, createIfNotExists=1):
130  v = self.parseXmlString(xml)
131  if type(v) is list:
132    for item in v:
133      id = _importXml(self,item,zms_system,createIfNotExists)
134  else:
135    id = _importXml(self,v,zms_system,createIfNotExists)
136
137
138# ------------------------------------------------------------------------------
139#  _metacmdmanager.getRawMetacmds:
140#
141#  Returns raw list of actions.
142# ------------------------------------------------------------------------------
143def getRawMetacmds(self):
144  return self.getConfProperty(CONF_METACMDS,[])
145
146
147# ------------------------------------------------------------------------------
148#  _metacmdmanager.delMetacmd:
149#
150#  Delete Action specified by given Id.
151# ------------------------------------------------------------------------------
152def delMetacmd(self, id):
153
154  # Catalog.
155  obs = copy.deepcopy(getRawMetacmds(self))
156  old = filter(lambda x: x['id']==id, obs)
157  if len(old) > 0:
158    obs.remove(old[0])
159  self.setConfProperty( CONF_METACMDS, obs)
160
161  # Remove Template.
162  self.manage_delObjects(ids=[id])
163
164  # Return with empty id.
165  return ''
166
167# ------------------------------------------------------------------------------
168#  _metacmdmanager.setMetacmd:
169#
170#  Set/add Action specified by given Id.
171# ------------------------------------------------------------------------------
172def setMetacmd(self, id, newId, newAcquired, newName='', newMethod=None, \
173      newData=None, newExec=0, newDescription='', newMetaTypes=[], \
174      newRoles=['ZMSAdministrator'], newCustom='', newNodes='{$}', zms_system=0):
175  obs = copy.deepcopy(getRawMetacmds(self))
176
177  # Catalog.
178  old = filter(lambda x: x['id'] in [id, newId], obs)
179  if len(old) > 0:
180    obs.remove(old[0])
181
182  # Values.
183  new = {}
184  new['id'] = newId
185  new['acquired'] = newAcquired
186  new['name'] = newName
187  new['description'] = newDescription
188  new['meta_types'] = newMetaTypes
189  new['roles'] = newRoles
190  new['custom'] = newCustom
191  new['nodes'] = newNodes
192  new['exec'] = newExec
193  new['zms_system'] = zms_system
194  obs.append(new)
195  self.setConfProperty( CONF_METACMDS, obs)
196
197  # Insert Template.
198  if id is None:
199    newTitle = '*** DO NOT DELETE OR MODIFY ***'
200    if newAcquired:
201      portalMaster = self.getPortalMaster()
202      if portalMaster is not None:
203        newMethod = getattr(portalMaster,newId).meta_type
204    if newId in self.objectIds():
205      self.manage_delObjects(ids=[newId])
206    if newMethod == 'DTML Method':
207      self.manage_addDTMLMethod(newId,newTitle)
208      if newData is None:
209        if newExec:
210          newData = dtmlMethodWithExecExampleCode
211        else:
212          newData = dtmlMethodWithoutExecExampleCode
213        newData = newData.replace('$$NAME$$',newName)
214    elif newMethod == 'DTML Document':
215      self.manage_addDTMLDocument(newId,newTitle)
216      if newData is None: newData = dtmlMethodExampleCode
217    elif newMethod == 'Page Template':
218      self.manage_addProduct['PageTemplates'].manage_addPageTemplate(id=newId,title=newTitle,text=pageTemplateExampleCode)
219    elif newMethod == 'Script (Python)':
220      PythonScript.manage_addPythonScript(self,newId)
221      if newData is None: newData = pyScriptExampleCode
222
223  # Rename Template.
224  elif id != newId:
225    self.manage_renameObject(id=id,new_id=newId)
226
227  # Update Template.
228  ob = getattr(self,newId,None)
229  if ob is not None:
230    if newAcquired:
231      newData = ''
232    if newData is not None:
233      if ob.meta_type in ['DTML Method','DTML Document']:
234        ob.manage_edit(title=ob.title,data=newData)
235      elif ob.meta_type == 'Page Template':
236        ob.pt_edit(newData,content_type=ob.content_type)
237      elif ob.meta_type == 'Script (Python)':
238        ob.write(newData)
239
240  # Return with new id.
241  return newId
242
243
244################################################################################
245################################################################################
246###
247###   class MetacmdObject
248###
249################################################################################
250################################################################################
251class MetacmdObject:
252
253    ############################################################################
254    #  MetacmdObject.manage_executeMetacmd:
255    #
256    #  Execute Meta-Command.
257    ############################################################################
258    def manage_executeMetacmd(self, custom, lang, REQUEST, RESPONSE):
259      """ MetacmdObject.manage_executeMetacmd """
260      message = ''
261      target = self
262     
263      # Execute.
264      # --------
265      for metaCmdId in self.getMetaCmdIds():
266        metaCmd = self.getMetaCmd(metaCmdId)
267        if metaCmd['name'] == custom:
268          # Acquire from parent.
269          if metaCmd.get('acquired',0) == 1:
270            portalMaster = self.getPortalMaster()
271            if portalMaster is not None:
272              masterDtmlMthd = getattr(portalMaster,metaCmd['id'])
273              ob = getattr(self,metaCmd['id'])
274              if ob.meta_type in [ 'DTML Method', 'DTML Document']:
275                newData = masterDtmlMthd.raw
276                ob.manage_edit(title=ob.title,data=newData)
277              elif ob.meta_type in [ 'Page Template']:
278                newData = masterDtmlMthd.read()
279                newContentType = masterDtmlMthd.content_type
280                ob.pt_edit(newData,content_type=newContentType)
281              elif ob.meta_type in [ 'Script (Python)']:
282                newData = masterDtmlMthd.read()
283                ob.ZPythonScript_setTitle( ob.title)
284                ob.write(newData)
285          # Execute directly.
286          if metaCmd.get('exec',0) == 1:
287            ob = getattr(self,metaCmd['id'],None)
288            if ob.meta_type in ['DTML Method','DTML Document']:
289              value = ob(self,REQUEST,RESPONSE)
290            elif ob.meta_type == 'Page Template':
291              value = ob()
292            elif ob.meta_type == 'Script (Python)':
293              value = ob()
294            if type(value) is str:
295              message = value
296            elif type(value) is tuple:
297              target = value[0]
298              message = value[1]
299          # Execute redirect.
300          else:
301            params = {'lang':REQUEST.get('lang'),'id_prefix':REQUEST.get('id_prefix'),'ids':REQUEST.get('ids',[])}
302            return RESPONSE.redirect(self.url_append_params(metaCmd['id'],params,sep='&'))
303     
304      # Return with message.
305      message = urllib.quote(message)
306      return RESPONSE.redirect('%s/manage_main?lang=%s&manage_tabs_message=%s'%(target.absolute_url(),lang,message))
307
308
309
310################################################################################
311################################################################################
312###
313###   class MetacmdManager
314###
315################################################################################
316################################################################################
317class MetacmdManager:
318
319    # Management Interface.
320    # ---------------------
321    manage_customizeMetacmdForm = HTMLFile('dtml/metacmd/manage_customizeform', globals())
322
323
324    def getMetaCmdDescription(self, id=None, name=None):
325      """
326      Returns description of meta-command specified by ID.
327      """
328      return self.getMetaCmd(id,name).get('description','')
329
330
331    # --------------------------------------------------------------------------
332    #  MetacmdManager.getMetaCmd
333    # --------------------------------------------------------------------------
334    def getMetaCmd(self, id=None, name=None):
335      obs = []
336      for x in getRawMetacmds(self):
337        # Acquire from parent.
338        if x.get('acquired',0)==1:
339          portalMaster = self.getPortalMaster()
340          if portalMaster is not None:
341            x = portalMaster.getMetaCmd(x['id'])
342            x['acquired'] = 1
343        else:
344          x = x.copy()
345        obs.append(x)
346      # Filter by Id.
347      if id is not None:
348        obs = filter(lambda x: x['id']==id, obs)
349      # Filter by Name.
350      if name is not None:
351        obs = filter(lambda x: x['name']==name, obs)
352      # Not found!
353      if len(obs) == 0:
354        return None
355      ob = obs[0]
356      ob['meta_type'] = getattr(self,ob['id']).meta_type
357      return ob
358
359
360    # --------------------------------------------------------------------------
361    #  MetacmdManager.getMetaCmdIds
362    #
363    #  Returns list of action-Ids.
364    # --------------------------------------------------------------------------
365    def getMetaCmdIds(self, sort=1):
366      obs = getRawMetacmds(self)
367      if sort:
368        obs = map(lambda x: self.getMetaCmd(x['id']), obs)
369        obs = filter( lambda x: x is not None, obs)
370        obs = map(lambda x: (x['name'],x), obs)
371        obs.sort()
372        obs = map(lambda x: x[1], obs)
373      ids = map(lambda x: x['id'], obs)
374      return ids
375
376
377    ############################################################################
378    #  MetacmdManager.manage_changeMetacmds:
379    #
380    #  Change Meta-Commands.
381    ############################################################################
382    def manage_changeMetacmds(self, btn, lang, REQUEST, RESPONSE):
383        """ MetacmdManager.manage_changeMetacmds """
384        message = ''
385        id = REQUEST.get('id','')
386       
387        # Acquire.
388        # --------
389        if btn == self.getZMILangStr('BTN_ACQUIRE'):
390          newId = REQUEST['aq_id']
391          newAcquired = 1
392          id = setMetacmd(self, None, newId, newAcquired)
393          message = self.getZMILangStr('MSG_INSERTED')%id
394       
395        # Change.
396        # -------
397        elif btn == self.getZMILangStr('BTN_SAVE'):
398          id = REQUEST['id']
399          newId = REQUEST['el_id']
400          newAcquired = 0
401          newName = REQUEST.get('el_name','').strip()
402          newMethod = None
403          newData = REQUEST.get('el_data','').strip()
404          newExec = REQUEST.get('el_exec',0)
405          newDescription = REQUEST.get('el_description','').strip()
406          newMetaTypes = REQUEST.get('el_meta_types',[])
407          newRoles = REQUEST.get('el_roles',[])
408          newCustom = REQUEST.get('el_custom','')
409          newNodes = REQUEST.get('el_nodes','')
410          id = setMetacmd(self, id, newId, newAcquired, newName, newMethod, newData, newExec, newDescription, \
411            newMetaTypes, newRoles, newCustom, newNodes)
412          message = self.getZMILangStr('MSG_CHANGED')
413       
414        # Copy.
415        # -----
416        elif btn == self.getZMILangStr('BTN_COPY'):
417          metaOb = self.getMetaCmd(id)
418          if metaOb.get('acquired',0) == 1:
419            portalMaster = self.getPortalMaster()
420            if portalMaster is not None:
421              REQUEST.set('ids',[id])
422              xml =  portalMaster.manage_changeMetacmds(self.getZMILangStr('BTN_EXPORT'), lang, REQUEST, RESPONSE)
423              importXml(self,xml=xml)
424              message = self.getZMILangStr('MSG_IMPORTED')%('<i>%s</i>'%id)
425       
426        # Delete.
427        # -------
428        elif btn == self.getZMILangStr('BTN_DELETE'):
429          id = delMetacmd(self,id)
430          message = self.getZMILangStr('MSG_DELETED')%int(1)
431       
432        # Export.
433        # -------
434        elif btn == self.getZMILangStr('BTN_EXPORT'):
435          value = []
436          ids = REQUEST.get('ids',[])
437          for metaCmdId in self.getMetaCmdIds():
438            if metaCmdId in ids or len(ids) == 0:
439              metaCmd = self.getMetaCmd(metaCmdId)
440              # Catalog.
441              el_id = metaCmdId
442              el_name = metaCmd['name']
443              el_description = metaCmd['description']
444              el_meta_types = metaCmd['meta_types']
445              el_roles = metaCmd['roles']
446              el_exec = metaCmd['exec']
447              el_custom = metaCmd.get('custom','')
448              # Object.
449              ob = getattr(self,metaCmdId)
450              el_meta_type = ob.meta_type
451              if ob.meta_type in ['DTML Method','DTML Document']:
452                el_data = ob.raw
453              elif ob.meta_type in ['Page Template']:
454                el_data = ob.read()
455              elif ob.meta_type in ['Script (Python)']:
456                el_data = ob.body()
457              # Value.
458              value.append({'id':el_id,'name':el_name,'description':el_description,'meta_types':el_meta_types,'roles':el_roles,'exec':el_exec,'custom':el_custom,'meta_type':el_meta_type,'data':el_data})
459          # XML.
460          if len(value)==1:
461            value = value[0]
462            filename = '%s.metacmd.xml'%value['id']
463          else:
464            filename = 'export.metacmd.xml'
465          content_type = 'text/xml; charset=utf-8'
466          export = self.getXmlHeader() + self.toXmlString(value,1)
467         
468          RESPONSE.setHeader('Content-Type',content_type)
469          RESPONSE.setHeader('Content-Disposition','inline;filename="%s"'%filename)
470          return export
471       
472        # Import.
473        # -------
474        elif btn == self.getZMILangStr('BTN_IMPORT'):
475          f = REQUEST['file']
476          if f:
477            filename = f.filename
478            importXml(self,xml=f)
479          else:
480            filename = REQUEST['init']
481            createIfNotExists = 1
482            self.importConf(filename, REQUEST, createIfNotExists)
483          message = self.getZMILangStr('MSG_IMPORTED')%('<i>%s</i>'%f.filename)
484       
485        # Insert.
486        # -------
487        elif btn == self.getZMILangStr('BTN_INSERT'):
488          newId = REQUEST.get('_id').strip()
489          newAcquired = 0
490          newName = REQUEST.get('_name').strip()
491          newMethod = REQUEST.get('_type','DTML Method')
492          newData = None
493          newExec = REQUEST.get('_exec',0)
494          id = setMetacmd(self, None, newId, newAcquired, newName, newMethod, newData, newExec)
495          message = self.getZMILangStr('MSG_INSERTED')%id
496       
497        # Return with message.
498        message = urllib.quote(message)
499        return RESPONSE.redirect('manage_customizeMetacmdForm?lang=%s&manage_tabs_message=%s&id=%s'%(lang,message,id))
500
501################################################################################
Note: See TracBrowser for help on using the repository browser.