source: ZMS/trunk/zmscontainerobject.py @ 1831

Revision 1831, 35.1 KB checked in by zmsdev, 2 months ago (diff)

ZMS2Go: prepared support for new simplified content-object model

Line 
1################################################################################
2# zmscontainerobject.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.Common import package_home
21from App.special_dtml import HTMLFile
22try: # Zope >= 2.13.0
23  from OFS.role import RoleManager
24except:
25  from AccessControl.Role import RoleManager
26import copy
27import re
28import string
29import sys
30import urllib
31import time
32# Product Imports.
33from zmsobject import ZMSObject
34import _accessmanager
35import _fileutil
36import _globals
37import _importable
38import _objattrs
39import _scormlib
40import _versionmanager
41import _zmi_actions_util
42
43__all__= ['ZMSContainerObject']
44
45
46# ------------------------------------------------------------------------------
47#  zmscontainerobject.isPageWithElements:
48# ------------------------------------------------------------------------------
49def isPageWithElements(obs):
50  for ob in obs:
51    if ob.isPageElement():
52      return True
53  return False
54
55
56# ------------------------------------------------------------------------------
57#  zmscontainerobject.getPrevSibling:
58#
59#  The node immediately preceding this node, otherwise returns None.
60# ------------------------------------------------------------------------------
61def getPrevSibling(self, REQUEST, incResource=False):
62  parent = self.getParentNode()
63  if parent is not None:
64    siblings = parent.getChildNodes(REQUEST,[self.PAGES,self.NORESOLVEREF])
65    if self in siblings:
66      i = siblings.index(self) - 1
67      while i >= 0:
68        ob = siblings[i]
69        if ob.isVisible(REQUEST) and (incResource or not ob.isResource(REQUEST)):
70          return ob
71        i = i - 1
72  return None
73
74# ------------------------------------------------------------------------------
75#  zmscontainerobject.getNextSibling:
76#
77#  The node immediately following this node, otherwise returns None.
78# ------------------------------------------------------------------------------
79def getNextSibling(self, REQUEST, incResource=False):
80  parent = self.getParentNode()
81  if parent is not None:
82    siblings = parent.getChildNodes(REQUEST,[self.PAGES,self.NORESOLVEREF])
83    siblingIds = map( lambda x: x.id, siblings)
84    if self.id in siblingIds:
85      i = siblingIds.index( self.id) + 1
86      while i < len(siblings):
87        ob = siblings[i]
88        if ob.isVisible(REQUEST) and (incResource or not ob.isResource(REQUEST)):
89          return ob
90        i = i + 1
91  return None
92
93
94
95################################################################################
96################################################################################
97###
98###   Abstract Class ZMSContainerObject
99###
100################################################################################
101################################################################################
102class ZMSContainerObject(
103    ZMSObject,
104    RoleManager,
105    _accessmanager.AccessableContainer,
106    _importable.Importable,
107    _scormlib.SCORMLib,
108    _versionmanager.VersionManagerContainer
109    ):
110
111    # Management Permissions.
112    # -----------------------
113    __administratorPermissions__ = (
114        'manage_system',
115        )
116    __ac_permissions__=(
117        ('ZMS Administrator', __administratorPermissions__),
118        )
119
120    # Interface.
121    # ----------
122    pageelement_TOC = HTMLFile('dtml/ZMSContainerObject/pageelement_toc', globals())
123
124    # Management Interface.
125    # ---------------------
126    manage_container = HTMLFile('dtml/ZMSContainerObject/manage_main', globals())
127    manage_main_btn = HTMLFile('dtml/ZMSContainerObject/manage_main_btn', globals())
128    manage_main_change = HTMLFile('dtml/ZMSContainerObject/manage_main_change', globals())
129    manage_main_actions = HTMLFile('dtml/ZMSContainerObject/manage_main_actions', globals())
130    manage_search = HTMLFile('dtml/ZMSContainerObject/manage_search', globals())
131    manage_search_attrs = HTMLFile('dtml/ZMSContainerObject/manage_search_attrs', globals())
132    manage_properties = HTMLFile('dtml/ZMSObject/manage_main', globals())
133    manage_system = HTMLFile('dtml/ZMSContainerObject/manage_system', globals())
134    manage_importexport = HTMLFile('dtml/ZMSContainerObject/manage_importexport', globals())
135    manage_importexportFtp = HTMLFile('dtml/ZMSContainerObject/manage_importexportftp', globals())
136
137
138    # Sitemap.
139    # --------
140    sitemap_layout0 = HTMLFile('dtml/ZMSContainerObject/sitemap/version0', globals())
141    sitemap_layout1 = HTMLFile('dtml/ZMSContainerObject/sitemap/version1', globals())
142    sitemap_layout2 = HTMLFile('dtml/ZMSContainerObject/sitemap/version2', globals())
143    sitemap_layout3 = HTMLFile('dtml/ZMSContainerObject/sitemap/version3', globals())
144
145
146    # Role Manager.
147    # -------------
148    def manage_addZMSCustom(self, meta_id, values={}, REQUEST=None):
149      values['meta_id'] = meta_id
150      return self.manage_addZMSObject('ZMSCustom',values,REQUEST)
151
152
153    # --------------------------------------------------------------------------
154    #  ZMSContainerObject.manage_addZMSObject:
155    # --------------------------------------------------------------------------
156    def manage_addZMSObject(self, meta_type, values, REQUEST):
157      prim_lang = self.getPrimaryLanguage()
158      lang = REQUEST.get('lang',prim_lang)
159     
160      attrs = []
161      for key in values.keys():
162        attrs.extend([key,values[key]])
163     
164      # Get id.
165      if 'id_prefix' in attrs:
166        i = attrs.index('id_prefix')
167        id_prefix = attrs[i+1]
168        id = self.getNewId(id_prefix)
169        del attrs[i] # Key.
170        del attrs[i] # Value.
171      elif 'id' in attrs:
172        i = attrs.index('id')
173        id = attrs[i+1]
174        del attrs[i] # Key.
175        del attrs[i] # Value.
176      else:
177        id = self.getNewId()
178     
179      # Get sort id.
180      key = 'sort_id'
181      if key in attrs and attrs.index(key)%2 == 0:
182        i = attrs.index(key)
183        sort_id = attrs[i+1]
184        del attrs[i] # Key.
185        del attrs[i] # Value.
186      else:
187        sort_id = 99999
188     
189      # Create new object.
190      newNode = self.dGlobalAttrs[meta_type]['obj_class'](id,sort_id)
191      self._setObject(newNode.id, newNode)
192      node = getattr(self,newNode.id)
193     
194      # Init meta object.
195      key = 'meta_id'
196      if meta_type == 'ZMSCustom' and key in attrs and attrs.index(key)%2 == 0:
197        i = attrs.index(key)
198        meta_id = attrs[i+1]
199        setattr(node,key,meta_id)
200        del attrs[i] # Key.
201        del attrs[i] # Value.
202     
203      # Object state.
204      node.setObjStateNew(REQUEST)
205     
206      # Init properties.
207      key = 'active'
208      if not (key in attrs and attrs.index(key)%2 == 0):
209        attrs.extend([key,1])
210      key = 'attr_dc_coverage'
211      if not (key in attrs and attrs.index(key)%2 == 0):
212        attrs.extend([key,'global.%s'%lang])
213      for i in range(len(attrs)/2):
214        key = attrs[i*2]
215        value = attrs[i*2+1]
216        node.setObjProperty(key,value,REQUEST['lang'])
217     
218      # Version manager.
219      node.onChangeObj(REQUEST)
220     
221      # Normalize sort-ids.
222      self.normalizeSortIds(_globals.id_prefix(id))
223     
224      # Return object.
225      return node
226
227
228    ############################################################################
229    ###
230    ###   Trashcan
231    ###
232    ############################################################################
233
234    # --------------------------------------------------------------------------
235    #  ZMSContainerObject.moveObjsToTrashcan
236    # --------------------------------------------------------------------------
237    def moveObjsToTrashcan(self, ids, REQUEST):
238      """
239      Move objects to trashcan.
240      @param ids: List of object-ids.
241      @type ids: C{list}
242      @rtype: C{None}
243      """
244      if self.meta_id == 'ZMSTrashcan':
245        return
246      trashcan = self.getTrashcan()
247      # Move (Cut & Paste).
248      try:
249        cb_copy_data = self.manage_cutObjects(ids,REQUEST)
250        trashcan.manage_pasteObjects(cb_copy_data=None,REQUEST=REQUEST)
251      except:
252        if len(ids) > 1:
253          except_ids = []
254          for id in ids:
255            try:
256              cb_copy_data = self.manage_cutObjects([id],REQUEST)
257              trashcan.manage_pasteObjects(cb_copy_data=None,REQUEST=REQUEST)
258            except:
259              except_ids.append(id)
260        else:
261          except_ids = ids
262        if len(except_ids) > 0:
263          _globals.writeError(self,'[moveObjsToTrashcan]: Unexpected Exception: ids=%s!'%str(except_ids))
264      trashcan.normalizeSortIds()
265      # Sort-IDs.
266      self.normalizeSortIds()
267
268
269    ############################################################################
270    #  ZMSContainerObject.manage_eraseObjs:
271    ############################################################################
272    def manage_eraseObjs(self, lang, ids, REQUEST, RESPONSE=None):
273      """
274      Delete a subordinate object physically:
275      The objects specified in 'ids' get deleted.
276      @param lang: Language-id.
277      @type ids: C{string}
278      @param ids: List of object-ids.
279      @type ids: C{list}
280      @param REQUEST: the triggering request
281      @type REQUEST: ZPublisher.HTTPRequest
282      @param RESPONSE: the triggering request
283      @type RESPONSE: ZPublisher.HTTPResponse
284      """
285     
286      message = ''
287      t0 = time.time()
288     
289      ##### Delete objects ####
290      count = len(ids)
291      self.manage_delObjects(ids=ids)
292     
293      # Return with message.
294      if RESPONSE is not None:
295        message += self.getZMILangStr('MSG_DELETED')%count
296        message += ' (in '+str(int((time.time()-t0)*100.0)/100.0)+' secs.)'
297        target = REQUEST.get('manage_target','manage_main')
298        return RESPONSE.redirect('%s?lang=%s&manage_tabs_message=%s'%(target,lang,urllib.quote(message)))
299
300
301    ############################################################################
302    #  ZMSContainerObject.manage_undoObjs:
303    ############################################################################
304    def manage_undoObjs(self, lang, ids, REQUEST, RESPONSE=None):
305      """
306      Undo a subordinate object:
307      The objects specified in 'ids' get undone (changes are rolled-back).
308      @param lang: Language-id.
309      @type ids: C{string}
310      @param ids: List of object-ids.
311      @type ids: C{list}
312      @param REQUEST: the triggering request
313      @type REQUEST: ZPublisher.HTTPRequest
314      @param RESPONSE: the triggering request
315      @type RESPONSE: ZPublisher.HTTPResponse
316      """
317     
318      message = ''
319      t0 = time.time()
320     
321      ##### Delete objects ####
322      c = 0
323      for child in self.getChildNodes():
324        if child.id in ids:
325          if child.inObjStates( [ 'STATE_NEW', 'STATE_MODIFIED', 'STATE_DELETED'], REQUEST):
326            child.rollbackObjChanges( self, REQUEST)
327            c += 1
328     
329      # Return with message.
330      if RESPONSE is not None:
331        message += self.getZMILangStr('MSG_UNDONE')%c
332        message += ' (in '+str(int((time.time()-t0)*100.0)/100.0)+' secs.)'
333        target = REQUEST.get('manage_target','manage_main')
334        return RESPONSE.redirect('%s?preview=preview&lang=%s&manage_tabs_message=%s'%(target,lang,urllib.quote(message)))
335
336
337    ############################################################################
338    #  ZMSContainerObject.manage_deleteObjs:
339    ############################################################################
340    def manage_deleteObjs(self, lang, ids, REQUEST, RESPONSE=None):
341      """
342      Delete a subordinate object logically:
343      The objects specified in 'ids' get deleted (moved to trashcan).
344      @param lang: Language-id.
345      @type ids: C{string}
346      @param ids: List of object-ids.
347      @type ids: C{list}
348      @param REQUEST: the triggering request
349      @type REQUEST: ZPublisher.HTTPRequest
350      @param RESPONSE: the triggering request
351      @type RESPONSE: ZPublisher.HTTPResponse
352      """
353     
354      message = ''
355      t0 = time.time()
356     
357      ##### Delete objects ####
358      versionMgrCntnrs = []
359      for child in self.getChildNodes():
360        if child.id in ids:
361          if child.getAutocommit() or child.inObjStates(['STATE_NEW'],REQUEST):
362            self.moveObjsToTrashcan([child.id], REQUEST)
363          else:
364            child.setObjStateDeleted(REQUEST)
365            versionCntnr = child.getVersionContainer()
366            if versionCntnr not in versionMgrCntnrs:
367              versionMgrCntnrs.append( versionCntnr)
368     
369      ##### VersionManager ####
370      for versionCntnr in versionMgrCntnrs:
371        versionCntnr.onChangeObj(REQUEST)
372     
373      # Return with message.
374      if RESPONSE is not None:
375        message += self.getZMILangStr('MSG_TRASHED')%len(ids)
376        message += ' (in '+str(int((time.time()-t0)*100.0)/100.0)+' secs.)'
377        target = REQUEST.get('manage_target','manage_main')
378        return RESPONSE.redirect('%s?preview=preview&lang=%s&manage_tabs_message=%s'%(target,lang,urllib.quote(message)))
379
380
381    # --------------------------------------------------------------------------
382    #  ZMSContainerObject.getContentType
383    # --------------------------------------------------------------------------
384    def getContentType( self, REQUEST):
385      """
386      Returns MIME-type (text/html).
387      @rtype: C{string}
388      """
389      return 'text/html'
390
391
392    ############################################################################
393    ###
394    ###  Drag'n Drop
395    ###
396    ############################################################################
397
398    # --------------------------------------------------------------------------
399    #  ZMSContainerObject.manage_ajaxDragDrop:
400    # --------------------------------------------------------------------------
401    def manage_ajaxDragDrop( self, lang, target, REQUEST, RESPONSE):
402      """ ZMSContainerObject.manage_ajaxDragDrop """
403      rc = 0
404      message = self.getZMILangStr('MSG_PASTED')
405      try:
406        before = False
407        into = False
408        if target.startswith('-'):
409          before = True
410          target = target[1:]
411        elif target.endswith('-'):
412          target = target[:-1]
413        else:
414          into = True
415        ob = self.getLinkObj( target)
416        sort_id = ob.getSortId()
417        if into:
418          sort_id = 0
419        else:
420          ob = ob.getParentNode()
421          if before:
422            sort_id = sort_id - 1
423          else:
424            sort_id = sort_id + 1
425        setattr( self, 'sort_id', _globals.format_sort_id(sort_id))
426        cb_copy_data = self.getParentNode().manage_cutObjects([self.id])
427        ob.manage_pasteObjects(cb_copy_data)
428        ob.normalizeSortIds()
429      except:
430        tp, vl, tb = sys.exc_info()
431        rc = -1
432        message = str(tp)+': '+str(vl)
433        _globals.writeError(self,'[manage_ajaxDragDrop]')
434      #-- Build xml.
435      RESPONSE = REQUEST.RESPONSE
436      content_type = 'text/xml; charset=utf-8'
437      filename = 'manage_ajaxDragDrop.xml'
438      RESPONSE.setHeader('Content-Type',content_type)
439      RESPONSE.setHeader('Content-Disposition','inline;filename="%s"'%filename)
440      RESPONSE.setHeader('Cache-Control', 'no-cache')
441      RESPONSE.setHeader('Pragma', 'no-cache')
442      self.f_standard_html_request( self, REQUEST)
443      xml = self.getXmlHeader()
444      xml += '<result code="%i" message="%s">\n'%(rc,message)
445      xml += "</result>\n"
446      return xml
447
448
449    ############################################################################
450    ###
451    ###  Page-Navigation
452    ###
453    ############################################################################
454
455    # --------------------------------------------------------------------------
456    #  ZMSContainerObject.getFirstPage:
457    # --------------------------------------------------------------------------
458    def getFirstPage(self, REQUEST, incResource=False, root=None):
459      """
460      Returns the first page of the tree from root (or document-element if root
461      is not given).
462      @param REQUEST: the triggering request
463      @type REQUEST: C{ZPublisher.HTTPRequest}
464      @return: the first page
465      @rtype: C{zmsobject.ZMSObject}
466      """
467      root = _globals.nvl(root,self.getDocumentElement())
468      return root
469   
470    # --------------------------------------------------------------------------
471    #  ZMSContainerObject.getPrevPage:
472    # --------------------------------------------------------------------------
473    def getPrevPage(self, REQUEST, incResource=False, root=None):
474      ob = None
475      root = _globals.nvl(root,self.getDocumentElement())
476      while True:
477        ob = getPrevSibling(self,REQUEST,incResource)
478        if ob is None:
479          parent = self.getParentNode()
480          if parent is not None:
481            if self.getHref2IndexHtml(REQUEST) == parent.getHref2IndexHtml(REQUEST):
482              ob = parent.getPrevPage(REQUEST,incResource,parent)
483            else:
484              ob = parent
485        else:
486          ob = ob.getLastPage(REQUEST,incResource,ob)
487        if not ob is None and not ob.isMetaType(self.PAGES,REQUEST):
488          ob = ob.getPrevPage(REQUEST,incResource,root)
489        if ob is None or ob.isMetaType(self.PAGES,REQUEST):
490          break
491      return ob
492
493    # --------------------------------------------------------------------------
494    #  ZMSContainerObject.getNextPage:
495    # --------------------------------------------------------------------------
496    def getNextPage(self, REQUEST, incResource=False, root=None):
497      ob = None
498      root = _globals.nvl(root,self.getDocumentElement())
499      while True:
500        children = self.filteredChildNodes(REQUEST,self.PAGES)
501        if len(children) > 0:
502          ob = children[0]
503        else:
504          current = self
505          while ob is None and current is not None:
506            ob = getNextSibling(current,REQUEST,incResource)
507            current = current.getParentNode()
508        if not ob is None and not ob.isMetaType(self.PAGES,REQUEST):
509          ob = ob.getNextPage(REQUEST,incResource,root)
510        if ob is None or ob.isMetaType(self.PAGES,REQUEST):
511          break
512      return ob
513
514    # --------------------------------------------------------------------------
515    #  ZMSContainerObject.getLastPage:
516    # --------------------------------------------------------------------------
517    def getLastPage(self, REQUEST, incResource=False, root=None):
518      """
519      Returns the last page of the tree from root (or document-element if root
520      is not given).
521      @param REQUEST: the triggering request
522      @type REQUEST: C{ZPublisher.HTTPRequest}
523      @return: the last page
524      @rtype: C{zmsobject.ZMSObject}
525      """
526      ob = None
527      root = _globals.nvl(root,self.getDocumentElement())
528      children = [root]
529      while len( children) > 0:
530        i = len( children)-1
531        while i >= 0:
532          if (incResource or not children[i].isResource(REQUEST)):
533            ob = children[i]
534            i = 0
535          i = i - 1
536        if ob == self:
537          break
538        children = ob.filteredChildNodes(REQUEST,self.PAGES)
539      return ob
540
541
542    ############################################################################
543    ### 
544    ###  Object-actions of management interface
545    ###
546    ############################################################################
547
548    def manage_ajaxZMIActions(self, context_id, REQUEST, RESPONSE):
549      """
550      Returns ZMI actions.
551     
552      @param REQUEST: the triggering request
553      @type REQUEST: C{ZPublisher.HTTPRequest}
554      @param RESPONSE: the response
555      @type RESPONSE: C{ZPublisher.HTTPResponse}
556      """
557     
558      #-- Get actions.
559      actions = []
560      container = self
561      objPath = ''
562      context = None
563      if context_id == '':
564        context = container
565        actions.extend( _zmi_actions_util.zmi_actions(self,self))
566      else:
567        attr_id = _globals.id_prefix(context_id)
568        if context_id in container.objectIds():
569            context = getattr(container,context_id,None)
570        actions.extend( _zmi_actions_util.zmi_actions(container,context,attr_id))
571        if context is not None:
572          objPath = context.id+'/'
573      if context is not None:
574        actions.extend( context.filtered_workflow_actions(objPath))
575     
576      #-- Build json.
577      RESPONSE.setHeader('Content-Type', 'text/plain; charset=utf-8')
578      RESPONSE.setHeader('Cache-Control', 'no-cache')
579      RESPONSE.setHeader('Pragma', 'no-cache')
580      return self.str_json({'id':context_id,'actions':map(lambda x: [x[0],x[1]], actions)})
581
582
583    ############################################################################
584    ###
585    ###  HTML-Presentation
586    ###
587    ############################################################################
588
589    # --------------------------------------------------------------------------
590    #  ZMSContainerObject.getNavItems:
591    # --------------------------------------------------------------------------
592    def getNavItems(self, current, REQUEST, opt={}, depth=0):
593      """
594      Returns html-formatted (unordered) list of navigation-items.
595      Uses the following classes
596        - I{current} item is current-element
597        - I{(in-)active} items is parent of current-element or current-element
598        - I{restricted} item has restricted access
599      @param current: the currently displayed page
600      @type current: C{zmsobject.ZMSObject}
601      @param REQUEST: the triggering request
602      @type REQUEST: C{ZPublisher.HTTPRequest}
603      @param opt: the dictionary of options
604          - I{id} (C{string=''}) id of base ul-element
605          - I{add_self} (C{boolean=False}) add self to list
606          - I{deep} (C{boolean=True}) process child nodes
607          - I{complete} (C{boolean=False}) process complete subtree
608          - I{maxdepth} (C{int=100}) limits node list to a given depth
609      @return: the Html
610      @rtype: C{string}
611      """
612      items = []
613      obs = []
614      if opt.get('add_self',False):
615        obs.append( self)
616        opt['add_self'] = False
617      obs.extend( self.filteredChildNodes(REQUEST,self.PAGES))
618      for ob in obs:
619        if not ob.isResource(REQUEST):
620          if len( items) == 0:
621            items.append( '<ul')
622            if opt.get('id',''):
623              items.append( ' id="%s"'%opt.get('id',''))
624              opt['id'] = ''
625            items.append('>\n')
626          css = []
627          if ob.id == current.id:
628            css.append( 'current')
629            css.append( 'active')
630            css.append( ob.meta_id + '1')
631          elif ob.id != self.id and ob.id in current.getPhysicalPath():
632            css.append( 'active')
633            css.append( ob.meta_id + '1')
634          else:
635            css.append( 'inactive')
636            css.append( ob.meta_id + '0')
637          if ob.getObjProperty( 'attr_dc_accessrights_restricted', REQUEST):
638            css.append( 'restricted')
639          items.append('<li')
640          items.append(' class="%s"'%(' '.join(css)))
641          items.append('>')
642          items.append('<a ')
643          items.append(' href="%s"'%ob.getHref2IndexHtml(REQUEST))
644          items.append(' title="%s"'%_globals.html_quote(ob.getTitle(REQUEST)))
645          if len(css) > 0:
646            items.append(' class="%s"'%(' '.join(css)))
647          items.append('>')
648          items.append('<span>%s</span>'%_globals.html_quote(ob.getTitlealt(REQUEST)))
649          items.append('</a>')
650          if (max(depth,ob.getLevel()) < opt.get('maxdepth',100)) and \
651             ((opt.get('complete',False)) or \
652              (opt.get('deep',True) and ob.id != self.id and \
653                (ob.id in current.getPhysicalPath() or \
654                 ob.id in REQUEST['URL'].split('/')))):
655            items.append( ob.getNavItems( current, REQUEST, opt, depth+1))
656          items.append('</li>\n')
657      if len( items) > 0:
658        items.append( '</ul>\n')
659      return ''.join(items)
660
661
662    # --------------------------------------------------------------------------
663    #  ZMSContainerObject.getNavElements:
664    #
665    #  Elements of main-navigation in content-area.
666    # --------------------------------------------------------------------------
667    def getNavElements(self, REQUEST, expand_tree=1, current_child=None, subElements=[]):
668      elmnts = []
669      # Child navigation.
670      obs = self.filteredChildNodes(REQUEST)
671      if not expand_tree and \
672         current_child is not None and \
673         current_child.meta_id in ['ZMS','ZMSFolder'] and \
674         isPageWithElements(obs) and \
675         self.getLevel() > 0:
676        obs = [current_child]
677      for ob in obs:
678        if ob.isPage() and not ob.isResource(REQUEST):
679          elmnts.append(ob)
680        if current_child is not None and \
681           current_child.id == ob.id:
682          elmnts.extend(subElements)
683      # Parent navigation.
684      parent = self.getParentNode()
685      if parent is not None:
686        elmnts = parent.getNavElements(REQUEST,expand_tree,self,elmnts)
687      # Return elements.
688      return elmnts
689
690
691    # --------------------------------------------------------------------------
692    #  ZMSContainerObject.getIndexNavElements:
693    #
694    #  Elements of index-navigation in content-area.
695    # --------------------------------------------------------------------------
696    def getIndexNavElements(self, REQUEST):
697      indexNavElmnts = []
698      # Retrieve elements.
699      if REQUEST.get('op','')=='':
700        indexNavElmnts = filter(lambda ob: ob.isPage() and ob.isMetaType(['ZMSDocument','ZMSCustom']) and not ob.isResource(REQUEST),self.filteredChildNodes(REQUEST,self.PAGES))
701      # Return elements.
702      return indexNavElmnts
703
704
705    ############################################################################
706    ###
707    ###   DOM-Methods
708    ###
709    ############################################################################
710
711    # --------------------------------------------------------------------------
712    #  ZMSContainerObject.filteredTreeNodes:
713    #
714    # --------------------------------------------------------------------------
715    def filteredTreeNodes(self, REQUEST, meta_types, order_by=None, order_dir=None, max_len=None, recursive=True):
716      """
717      Returns a NodeList that contains all visible children of this subtree
718      in correct order. If none, this is a empty NodeList.
719      """
720      rtn = []
721     
722      #-- Process tree.
723      if not self.meta_type == 'ZMSLinkElement':
724        obs = self.getChildNodes(REQUEST)
725        for ob in obs:
726          append = True
727          append = append and ob.isMetaType(meta_types)
728          append = append and ob.isVisible(REQUEST)
729          if append:
730            rtn.append(ob)
731          if not append or (append and recursive):
732            if ob.isPage():
733              rtn.extend(ob.filteredTreeNodes(REQUEST,meta_types,None,order_dir,None,recursive))
734     
735      #-- Order.
736      if order_by is not None:
737     
738        # order by select-options of special object
739        options = []
740        if type(meta_types) is str and meta_types in self.getMetaobjIds():
741          metaObj = self.getMetaobj(meta_types)
742          attrs = metaObj['attrs']
743          for attr in attrs:
744            if attr['id'] == order_by:
745              options = attr.get('keys',[])
746     
747        # collect object-items
748        tmp = []
749        for ob in rtn:
750          value = ob.getObjProperty(order_by,REQUEST)
751          if value in options:
752            value = options.index(value)
753          tmp.append((value,ob))
754       
755        # sort object-items
756        tmp.sort()
757       
758        # truncate sort-id from sorted object-items
759        rtn = map( lambda ob: ob[1], tmp)
760        if order_dir == 'desc':
761          rtn.reverse()
762     
763      #-- Size.
764      if max_len is not None:
765        if len(rtn) > max_len:
766          rtn = rtn[:max_len]
767     
768      return rtn
769
770
771    # --------------------------------------------------------------------------
772    #  ZMSContainerObject.firstFilteredChildNode:
773    # --------------------------------------------------------------------------
774    def firstFilteredChildNode(self, REQUEST={}, meta_types=None):
775      """
776      Returns the first visible child of this node.
777      """
778      for node in self.getChildNodes(REQUEST,meta_types):
779        if node.isVisible(REQUEST):
780          return node
781      return None
782
783
784    # --------------------------------------------------------------------------
785    #  ZMSContainerObject.filteredChildNodes:
786    #
787    # --------------------------------------------------------------------------
788    def filteredChildNodes(self, REQUEST={}, meta_types=None):
789      """
790      Returns a NodeList that contains all visible children of this node in
791      correct order. If none, this is a empty NodeList.
792      """
793      return filter(lambda ob: ob.isVisible(REQUEST),self.getChildNodes(REQUEST,meta_types))
794
795
796    # --------------------------------------------------------------------------
797    #  ZMSContainerObject.getChildNodes:
798    #
799    # --------------------------------------------------------------------------
800    def getChildNodes(self, REQUEST=None, meta_types=None, reid=None):
801      """
802      Returns a NodeList that contains all children of this node in correct
803      order. If none, this is a empty NodeList.
804      """
805      childNodes = []
806      types = self.dGlobalAttrs.keys()
807      obs = self.objectValues( types)
808      # Filter ids.
809      if reid:
810        pattern = re.compile( reid)
811        obs = filter( lambda x: pattern.match( x.id), obs)
812      # Get all object-items.
813      if REQUEST is None:
814        childNodes = map( lambda x: ( getattr( x, 'sort_id', ''), x), obs)
815      # Get selected object-items.
816      else:
817        prim_lang = self.getPrimaryLanguage()
818        lang = REQUEST.get('lang',None)
819        # Get coverages.
820        coverages = [ '', 'obligation', None]
821        if lang is not None:
822          coverages.extend( [ 'global.'+lang, 'local.'+lang])
823          coverages.extend( map( lambda x: 'global.'+x, self.getParentLanguages( lang)))
824        for ob in filter( lambda x: x.isMetaType( meta_types, REQUEST), obs):
825          coverage = None
826          if lang is not None:
827            obj_vers = ob.getObjVersion( REQUEST)
828            coverage = getattr( obj_vers, 'attr_dc_coverage', '')
829          if coverage in coverages:
830            proxy = ob.__proxy__()
831            if proxy is not None:
832              sort_id = getattr( ob, 'sort_id', '')
833              if ob.isPage():
834                sort_id = 's' + sort_id
835              childNodes.append( ( sort_id, proxy))
836      # Sort child-nodes.
837      childNodes.sort()
838      # Return child-nodes in correct sort-order.
839      return map(lambda x: x[1],childNodes)
840
841
842    ############################################################################
843    ### 
844    ###  Sort-Order
845    ###
846    ############################################################################
847
848    # --------------------------------------------------------------------------
849    #  ZMSContainerObject.normalizeSortIds:
850    #
851    #  Normalizes sort-ids for all children of this node
852    # --------------------------------------------------------------------------
853    def normalizeSortIds(self, id_prefix='e'):
854      # Get all object-items.
855      obs = []
856      for ob in self.objectValues( self.dGlobalAttrs.keys()):
857        sort_id = getattr( ob, 'sort_id', '')
858        proxy = ob.__proxy__()
859        if proxy is not None:
860          sort_id = getattr( ob, 'sort_id', '')
861          if proxy.isPage(): sort_id = 's%s'%sort_id
862          obs.append((sort_id,ob))
863      # Sort child-nodes.
864      obs.sort()
865      # Normalize sort-order.
866      new_sort_id = 10
867      for ( sort_id, ob) in obs:
868       if ob.id[:len(id_prefix)] == id_prefix:
869         ob.setSortId( new_sort_id)
870         new_sort_id  += 10
871
872
873    # --------------------------------------------------------------------------
874    #  ZMSContainerObject.getNewSortId:
875    #
876    #  Get new Sort-ID.
877    # --------------------------------------------------------------------------
878    def getNewSortId(self):
879      new_sort_id = 0
880      for ob in self.getChildNodes():
881        sort_id = ob.getSortId()
882        if sort_id > new_sort_id:
883          new_sort_id = sort_id
884      new_sort_id = new_sort_id + 10
885      return new_sort_id
886
887
888    ############################################################################
889    #
890    #   Module
891    #
892    ############################################################################
893
894    # --------------------------------------------------------------------------
895    #  ZMSContainerObject.manage_addZMSCustomDefault:
896    # --------------------------------------------------------------------------
897    def manage_addZMSCustomDefault(self, lang, id_prefix, _sort_id, REQUEST, RESPONSE):
898      """
899      Add default.
900      """
901      attr = self.getMetaobjAttr( self.meta_id, id_prefix)
902      zexp = attr[ 'custom']
903      new_id = self.getNewId(id_prefix)
904      _fileutil.import_zexp(self,zexp,new_id,id_prefix,_sort_id)
905     
906      # Return with message.
907      message = self.getZMILangStr('MSG_INSERTED')%attr['name']
908      RESPONSE.redirect('%s/%s/manage_main?lang=%s&manage_tabs_message=%s'%(self.absolute_url(),new_id,lang,urllib.quote(message)))
909
910    # --------------------------------------------------------------------------
911    #  ZMSContainerObject.manage_addZMSModule:
912    # --------------------------------------------------------------------------
913    def manage_addZMSModule(self, lang, _sort_id, custom, REQUEST, RESPONSE):
914      """
915      Add module.
916      """
917      meta_id = self.getMetaobjId( custom)
918      metaObj = self.getMetaobj( meta_id)
919      key = self.getMetaobjAttrIds( meta_id)[0]
920      attr = self.getMetaobjAttr( meta_id, key)
921      zexp = attr[ 'custom']
922      id_prefix = _globals.id_prefix(REQUEST.get('id_prefix','e'))
923      new_id = self.getNewId(id_prefix)
924      _fileutil.import_zexp(self,zexp,new_id,id_prefix,_sort_id)
925     
926      # Return with message.
927      message = self.getZMILangStr('MSG_INSERTED')%custom
928      RESPONSE.redirect('%s/%s/manage_main?lang=%s&manage_tabs_message=%s'%(self.absolute_url(),new_id,lang,urllib.quote(message)))
929
930################################################################################
Note: See TracBrowser for help on using the repository browser.