-
-
Notifications
You must be signed in to change notification settings - Fork 186
/
StatelessTree.py
201 lines (171 loc) · 7.3 KB
/
StatelessTree.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
from types import StringType, UnicodeType
from OFS.SimpleItem import SimpleItem
from DateTime import DateTime
from AccessControl import Unauthorized, getSecurityManager
from StatelessTreeNav import StatelessTreeBuilder
from Products.CMFCore.utils import getToolByName
from ZODB.POSException import ConflictError
def constructNavigationTreeViewBuilder(self, **kwargs):
""" """
ntvb=NavigationTreeViewBuilder(**kwargs)
return ntvb
class NavigationTreeViewBuilder(SimpleItem):
""" Please do not attach this object to the ZODB graph """
def __init__(self, **kwargs):
setattr(self, 'ids', kwargs.keys())
for k, v in kwargs.items():
setattr(self, k, v)
def getContext(self):
return self.aq_parent.aq_parent
def __call__(self):
""" return the data structure """
context=self.getContext()
navtree_properties=getToolByName(self, 'portal_properties').navtree_properties
props=getattr(context,'navtree_properties', navtree_properties)
#XXX The above is highly inefficient I believe
for k, v in props.propertyItems():
if getattr(self, k, None) is None:
setattr(self, k, getattr(context, k, v))
self.sortCriteria=[c for c in self.sortCriteria
if type(c) in (UnicodeType, StringType) and c.strip()]
tb=StatelessTreeBuilder(context, topObject=self.tree_root,
childFinder=self.childFinder, includeTop=self.includeTop,
showFolderishSiblingsOnly=self.showFolderishSiblingsOnly,
showFolderishChildrenOnly=self.showFolderishChildrenOnly,
showNonFolderishObject=self.showNonFolderishObject,
topLevel=self.topLevel, forceParentsInBatch=self.forceParentsInBatch,
skipIndex_html=self.skipIndex_html,bottomLevel=self.bottomLevel,
idsNotToList=getattr(self,'idsNotToList',[])
)
batchStart=None
batchSize=self.batchSize
if self.navBatchStart is None:
batchStart=None
else:
batchStart=int(self.navBatchStart)
#from where to start? is called automatically by the .pt
res=tb.buildFlatMenuStructure( batchSize=batchSize,
batchStart=batchStart )
for r in res['list']:
r['published'] = self.checkPublished(r['object'])
return res
# checks if an object is published respecting its
# publishing dates
# XXX I did not find this in the API but there
# should be something like this....
def checkPublished(self, o):
user=getSecurityManager().getUser()
showUnpublishedContent = user.has_role(self.rolesSeeUnpublishedContent,o)
try:
if showUnpublishedContent:
return showUnpublishedContent
workflow_tool = getToolByName(self, 'portal_workflow')
if workflow_tool.getInfoFor(o,'review_state','') != 'published':
return 0
now = DateTime()
start_pub = getattr(o,'effective_date',None)
end_pub = getattr(o,'expiration_date',None)
if start_pub and start_pub > now:
return 0
if end_pub and now > end_pub:
return 0
except ConflictError:
raise
except:
return 0
return 1
#default function that finds the children out of a folderish object
def childFinder(self,obj,folderishOnly=1):
user=getSecurityManager().getUser()
portal=self.aq_parent.aq_inner
catalog=portal.portal_catalog
getpath=catalog.getpath
perm_check=portal.portal_membership.checkPermission
# the 'important' users may see unpublished content
# who can see unpublished content may also see hidden files
showHiddenFiles = user.has_role(self.rolesSeeHiddenContent or [],obj)
try:
if obj.meta_type in self.parentMetaTypesNotToQuery:
return []
# shall all Members be listed or just myself!
if self.showMyUserFolderOnly and obj == portal.portal_membership.getMembersFolder():
try:
return [getattr(obj,user.getId())]
except (KeyError, AttributeError):
return []
# to traverse through Portal Topics
if obj.meta_type == 'Portal Topic':
#in order to view all topic results in the tree
folderishOnly=not self.showTopicResults
res=obj.listFolderContents(suppressHiddenFiles=not showHiddenFiles)
subs=obj.queryCatalog()
# get the objects out of the cat results
for s in subs:
try:
o=context.restrictedTraverse(getpath(s.data_record_id_))
res.append(wrap_obj(o,obj))
except (Unauthorized, 'Unauthorized'):
pass
else:
#traversal to all 'CMFish' folders
if hasattr(obj.aq_explicit,'listFolderContents'):
try:
res=obj.listFolderContents(suppressHiddenFiles=not showHiddenFiles)
except TypeError:
# if the suppressHiddenFiles param is not supported
res=obj.listFolderContents()
else:
res=obj.contentValues() #and all other *CMF* folders
rs=[]
for r in res: #filter out metatypes and by except:pass
#all objs producing an error
try:
if r.meta_type not in self.metaTypesNotToList and r.id not in self.idsNotToList:
rs.append(r)
except ConflictError:
raise
except:
pass
res=rs
# if wanted just keep folderish objects
if folderishOnly:
objs=[x for x in res if getattr(x,'isPrincipiaFolderish',None)]
perm = 'View' #XXX should be imported
res = [o for o in objs if perm_check(perm, o)]
res = [o for o in res if self.checkPublished(o) ]
try:
res.sort(self._navtree_cmp) #if sorting fails - never mind, it shall not break nav
except ConflictError:
raise
except:
pass
return res
except ConflictError:
raise
except:
return []
def _navtree_cmp(self, a,b):
for cs in self.sortCriteria:
c=cs.split(',')
field=c[0]
if len(c)==2:
order=c[1]
else:
order='asc'
if hasattr(a,field) and hasattr(b,field):
aval=getattr(a,field)
if callable(aval): aval = aval()
bval=getattr(b,field)
if callable(bval): bval = bval()
if order == 'desc':
aval,bval = bval,aval
try:
aval=aval.lower()
bval=bval.lower()
except AttributeError:
pass
if aval < bval:
return -1
elif bval < aval:
return 1
return 0