Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 469 lines (416 sloc) 18.499 kb
e5cce60 @chrisglass Encoding changes for the rest of the CMS stuff.
chrisglass authored
1 # -*- coding: utf-8 -*-
b8b54ba @ojii Added more tests for view permission in menu
ojii authored
2 from collections import defaultdict
6be7842 @ojii Improved menu building by getting all view permissions at once for all p...
ojii authored
3 from cms.apphook_pool import apphook_pool
4 from cms.models.moderatormodels import (ACCESS_DESCENDANTS,
35c0b88 @FrankBie menu shows now right pages for different group and granttypes
FrankBie authored
5 ACCESS_PAGE_AND_DESCENDANTS, ACCESS_CHILDREN, ACCESS_PAGE_AND_CHILDREN, ACCESS_PAGE)
6be7842 @ojii Improved menu building by getting all view permissions at once for all p...
ojii authored
6 from cms.models.permissionmodels import PagePermission, GlobalPagePermission
7 from cms.models.titlemodels import Title
589de2c @digi604 some start of the menu discover infrastructure
digi604 authored
8 from cms.utils import get_language_from_request
6be7842 @ojii Improved menu building by getting all view permissions at once for all p...
ojii authored
9 from cms.utils.i18n import get_fallback_languages
589de2c @digi604 some start of the menu discover infrastructure
digi604 authored
10 from cms.utils.moderator import get_page_queryset, get_title_queryset
6be7842 @ojii Improved menu building by getting all view permissions at once for all p...
ojii authored
11 from cms.utils.plugins import current_site
12 from menus.base import Menu, NavigationNode, Modifier
13 from menus.menu_pool import menu_pool
589de2c @digi604 some start of the menu discover infrastructure
digi604 authored
14
e9e36e6 @FrankBie2 removed edgecases
FrankBie2 authored
15 from django.conf import settings
16 from django.contrib.sites.models import Site
17 from django.db.models.query_utils import Q
18 from django.contrib.auth.models import Permission
6be7842 @ojii Improved menu building by getting all view permissions at once for all p...
ojii authored
19
d7aa9c8 @ojii Drastically improved coverage of cms.menu.get_visible_pages and fixed so...
ojii authored
20 def get_visible_pages(request, pages, site=None):
a5a7092 @FrankBie2 code cleanup
FrankBie2 authored
21 """
22 This code is basically a many-pages-at-once version of
23 Page.has_view_permission.
24 pages contains all published pages
25 check if there is ANY restriction
26 that needs a permission page visibility calculation
27 """
28 is_setting_public_all = settings.CMS_PUBLIC_FOR == 'all'
29 is_setting_public_staff = settings.CMS_PUBLIC_FOR == 'staff'
30 is_auth_user = request.user.is_authenticated()
35c0b88 @FrankBie menu shows now right pages for different group and granttypes
FrankBie authored
31
7dd2341 @FrankBie2 menu rendering tests for grant options
FrankBie2 authored
32 visible_page_ids = []
33 restricted_pages = defaultdict(list)
6be7842 @ojii Improved menu building by getting all view permissions at once for all p...
ojii authored
34 pages_perms_q = Q()
7dd2341 @FrankBie2 menu rendering tests for grant options
FrankBie2 authored
35
6be7842 @ojii Improved menu building by getting all view permissions at once for all p...
ojii authored
36 for page in pages:
7107eb4 @FrankBie2 add test for issue #1113
FrankBie2 authored
37 # taken from for_page as multiple at once version
35c0b88 @FrankBie menu shows now right pages for different group and granttypes
FrankBie authored
38 page_q = Q(page__tree_id=page.tree_id) & (
6be7842 @ojii Improved menu building by getting all view permissions at once for all p...
ojii authored
39 Q(page=page)
35c0b88 @FrankBie menu shows now right pages for different group and granttypes
FrankBie authored
40 | (Q(page__level__lt=page.level) & (Q(grant_on=ACCESS_DESCENDANTS) | Q(grant_on=ACCESS_PAGE_AND_DESCENDANTS)))
41 | (Q(page__level=page.level - 1) & (Q(grant_on=ACCESS_CHILDREN) | Q(grant_on=ACCESS_PAGE_AND_CHILDREN)))
6be7842 @ojii Improved menu building by getting all view permissions at once for all p...
ojii authored
42 )
35c0b88 @FrankBie menu shows now right pages for different group and granttypes
FrankBie authored
43 pages_perms_q |= page_q
db0fdae @FrankBie2 fixed tests that had page.level = None
FrankBie2 authored
44
a5a7092 @FrankBie2 code cleanup
FrankBie2 authored
45
35c0b88 @FrankBie menu shows now right pages for different group and granttypes
FrankBie authored
46 pages_perms_q &= Q(can_view=True)
47 page_permissions = PagePermission.objects.filter(pages_perms_q).select_related('page', 'group__users')
48
49 for perm in page_permissions:
a5a7092 @FrankBie2 code cleanup
FrankBie2 authored
50 # collect the pages that are affected by permissions
35c0b88 @FrankBie menu shows now right pages for different group and granttypes
FrankBie authored
51 if perm is not None and perm not in restricted_pages[perm.page.pk]:
a5a7092 @FrankBie2 code cleanup
FrankBie2 authored
52 # affective restricted pages gathering
35c0b88 @FrankBie menu shows now right pages for different group and granttypes
FrankBie authored
53 # using mptt functions
54 # add the page with the perm itself
0aa3a1a @FrankBie2 cms public for staff : but no staff user test, menu not rendered correct...
FrankBie2 authored
55 if perm.grant_on in [ACCESS_PAGE, ACCESS_PAGE_AND_CHILDREN ,ACCESS_PAGE_AND_DESCENDANTS]:
35c0b88 @FrankBie menu shows now right pages for different group and granttypes
FrankBie authored
56 restricted_pages[perm.page.pk].append(perm)
57 # add children
58 if perm.grant_on in [ACCESS_CHILDREN, ACCESS_PAGE_AND_CHILDREN]:
59 child_ids = perm.page.get_children().values_list('id', flat=True)
60 for id in child_ids:
61 restricted_pages[id].append(perm)
62 # add descendants
63 elif perm.grant_on in [ACCESS_DESCENDANTS, ACCESS_PAGE_AND_DESCENDANTS]:
64 child_ids = perm.page.get_descendants().values_list('id', flat=True)
65 for id in child_ids:
66 restricted_pages[id].append(perm)
a5a7092 @FrankBie2 code cleanup
FrankBie2 authored
67 # anonymous
68 # no restriction applied at all
69 if (not is_auth_user and
70 is_setting_public_all and
942cf4f @FrankBie2 pep8 fixes
FrankBie2 authored
71 not restricted_pages):
a5a7092 @FrankBie2 code cleanup
FrankBie2 authored
72 return [page.pk for page in pages]
73
74
d7aa9c8 @ojii Drastically improved coverage of cms.menu.get_visible_pages and fixed so...
ojii authored
75 if site is None:
76 site = current_site(request)
6be7842 @ojii Improved menu building by getting all view permissions at once for all p...
ojii authored
77
a5a7092 @FrankBie2 code cleanup
FrankBie2 authored
78 # authenticated user and global permission
79 if is_auth_user:
6be7842 @ojii Improved menu building by getting all view permissions at once for all p...
ojii authored
80 global_page_perm_q = Q(
81 Q(user=request.user) | Q(group__user=request.user)
d7aa9c8 @ojii Drastically improved coverage of cms.menu.get_visible_pages and fixed so...
ojii authored
82 ) & Q(can_view=True) & Q(Q(sites__in=[site.pk]) | Q(sites__isnull=True))
6be7842 @ojii Improved menu building by getting all view permissions at once for all p...
ojii authored
83 global_view_perms = GlobalPagePermission.objects.filter(global_page_perm_q).exists()
a5a7092 @FrankBie2 code cleanup
FrankBie2 authored
84
85 #no page perms edgcase - all visible
86 if ((is_setting_public_all or (
87 is_setting_public_staff and request.user.is_staff))and
942cf4f @FrankBie2 pep8 fixes
FrankBie2 authored
88 not restricted_pages and
89 not global_view_perms):
a5a7092 @FrankBie2 code cleanup
FrankBie2 authored
90 return [page.pk for page in pages]
91 #no page perms edgcase - none visible
92 elif (is_setting_public_staff and
93 not request.user.is_staff and
942cf4f @FrankBie2 pep8 fixes
FrankBie2 authored
94 not restricted_pages and
95 not global_view_perms):
a5a7092 @FrankBie2 code cleanup
FrankBie2 authored
96 return []
97
6be7842 @ojii Improved menu building by getting all view permissions at once for all p...
ojii authored
98
d7aa9c8 @ojii Drastically improved coverage of cms.menu.get_visible_pages and fixed so...
ojii authored
99 def has_global_perm():
100 if has_global_perm.cache < 0:
101 has_global_perm.cache = 1 if request.user.has_perm('cms.view_page') else 0
102 return bool(has_global_perm.cache)
103 has_global_perm.cache = -1
104
7dd2341 @FrankBie2 menu rendering tests for grant options
FrankBie2 authored
105 def has_permission_membership(page):
b8b54ba @ojii Added more tests for view permission in menu
ojii authored
106 """
7dd2341 @FrankBie2 menu rendering tests for grant options
FrankBie2 authored
107 PagePermission user group membership tests
b8b54ba @ojii Added more tests for view permission in menu
ojii authored
108 """
0aa3a1a @FrankBie2 cms public for staff : but no staff user test, menu not rendered correct...
FrankBie2 authored
109 user_pk = request.user.pk
110 page_pk = page.pk
111 has_perm = False
7dd2341 @FrankBie2 menu rendering tests for grant options
FrankBie2 authored
112 for perm in restricted_pages[page_pk]:
113 if perm.user_id == user_pk:
0aa3a1a @FrankBie2 cms public for staff : but no staff user test, menu not rendered correct...
FrankBie2 authored
114 has_perm = True
b8b54ba @ojii Added more tests for view permission in menu
ojii authored
115 if not perm.group_id:
116 continue
0aa3a1a @FrankBie2 cms public for staff : but no staff user test, menu not rendered correct...
FrankBie2 authored
117 group_user_ids = perm.group.user_set.values_list('pk', flat=True)
942cf4f @FrankBie2 pep8 fixes
FrankBie2 authored
118 if user_pk in group_user_ids:
0aa3a1a @FrankBie2 cms public for staff : but no staff user test, menu not rendered correct...
FrankBie2 authored
119 has_perm = True
120 return has_perm
6be7842 @ojii Improved menu building by getting all view permissions at once for all p...
ojii authored
121
122 for page in pages:
0aa3a1a @FrankBie2 cms public for staff : but no staff user test, menu not rendered correct...
FrankBie2 authored
123 to_add = False
a5a7092 @FrankBie2 code cleanup
FrankBie2 authored
124 # default to false, showing a restricted page is bad
125 # explicitly check all the conditions
126 # of settings and permissions
b8b54ba @ojii Added more tests for view permission in menu
ojii authored
127 is_restricted = page.pk in restricted_pages
a5a7092 @FrankBie2 code cleanup
FrankBie2 authored
128 # restricted_pages contains as key any page.pk that is
129 # affected by a permission grant_on
0aa3a1a @FrankBie2 cms public for staff : but no staff user test, menu not rendered correct...
FrankBie2 authored
130 if is_auth_user:
6be7842 @ojii Improved menu building by getting all view permissions at once for all p...
ojii authored
131 # a global permission was given to the request's user
132 if global_view_perms:
0aa3a1a @FrankBie2 cms public for staff : but no staff user test, menu not rendered correct...
FrankBie2 authored
133 to_add = True
a5a7092 @FrankBie2 code cleanup
FrankBie2 authored
134 # setting based handling of unrestricted pages
135 elif not is_restricted and (
136 is_setting_public_all or (
137 is_setting_public_staff and request.user.is_staff)
138 ):
139 # authenticated user, no restriction and public for all
140 # or
141 # authenticated staff user, no restriction and public for staff
142 to_add = True
143 # check group and user memberships to restricted pages
7dd2341 @FrankBie2 menu rendering tests for grant options
FrankBie2 authored
144 elif is_restricted and has_permission_membership(page):
0aa3a1a @FrankBie2 cms public for staff : but no staff user test, menu not rendered correct...
FrankBie2 authored
145 to_add = True
d7aa9c8 @ojii Drastically improved coverage of cms.menu.get_visible_pages and fixed so...
ojii authored
146 elif has_global_perm():
0aa3a1a @FrankBie2 cms public for staff : but no staff user test, menu not rendered correct...
FrankBie2 authored
147 to_add = True
a5a7092 @FrankBie2 code cleanup
FrankBie2 authored
148 # anonymous user, no restriction
149 elif not is_restricted and is_setting_public_all:
0aa3a1a @FrankBie2 cms public for staff : but no staff user test, menu not rendered correct...
FrankBie2 authored
150 to_add = True
a5a7092 @FrankBie2 code cleanup
FrankBie2 authored
151 # store it
0aa3a1a @FrankBie2 cms public for staff : but no staff user test, menu not rendered correct...
FrankBie2 authored
152 if to_add:
7dd2341 @FrankBie2 menu rendering tests for grant options
FrankBie2 authored
153 visible_page_ids.append(page.pk)
154 return visible_page_ids
f30f623 @fivethreeo less queries when rendering menus
fivethreeo authored
155
38225bb @digi604 testsuite working again
digi604 authored
156 def page_to_node(page, home, cut):
fc35b42 @chrisglass Added comments to code (!) and generally tweaked readability (because it...
chrisglass authored
157 '''
158 Transform a CMS page into a navigation node.
159
160 page: the page you wish to transform
161 home: a reference to the "home" page (the page with tree_id=1)
162 cut: Should we cut page from it's parent pages? This means the node will not
163 have a parent anymore.
164 '''
165 # Theses are simple to port over, since they are not calculated.
166 # Other attributes will be added conditionnally later.
167 attr = {'soft_root':page.soft_root,
168 'auth_required':page.login_required,
169 'reverse_id':page.reverse_id,}
170
38225bb @digi604 testsuite working again
digi604 authored
171 parent_id = page.parent_id
fc35b42 @chrisglass Added comments to code (!) and generally tweaked readability (because it...
chrisglass authored
172 # Should we cut the Node from its parents?
38225bb @digi604 testsuite working again
digi604 authored
173 if home and page.parent_id == home.pk and cut:
174 parent_id = None
fc35b42 @chrisglass Added comments to code (!) and generally tweaked readability (because it...
chrisglass authored
175
eb76ac9 @ojii fixed cache invalidation for menu
ojii authored
176 # possible fix for a possible problem
177 #if parent_id and not page.parent.get_calculated_status():
178 # parent_id = None # ????
fc35b42 @chrisglass Added comments to code (!) and generally tweaked readability (because it...
chrisglass authored
179
3c2fc7d @stefanfoulis added ability to display a page only for anonymous user (as well as only...
stefanfoulis authored
180 if page.limit_visibility_in_menu == None:
181 attr['visible_for_authenticated'] = True
182 attr['visible_for_anonymous'] = True
183 else:
184 attr['visible_for_authenticated'] = page.limit_visibility_in_menu == 1
185 attr['visible_for_anonymous'] = page.limit_visibility_in_menu == 2
fc35b42 @chrisglass Added comments to code (!) and generally tweaked readability (because it...
chrisglass authored
186
ba6ca93 @digi604 fixed testsuite and even reduced 2 queries .. yehaa
digi604 authored
187 if page.pk == home.pk:
188 attr['is_home'] = True
fc35b42 @chrisglass Added comments to code (!) and generally tweaked readability (because it...
chrisglass authored
189
190 # Extenders can be either navigation extenders or from apphooks.
191 extenders = []
6967eea @digi604 apphooks working, nav extenders as well
digi604 authored
192 if page.navigation_extenders:
193 extenders.append(page.navigation_extenders)
fc35b42 @chrisglass Added comments to code (!) and generally tweaked readability (because it...
chrisglass authored
194 # Is this page an apphook? If so, we need to handle the apphooks's nodes
11d0622 @digi604 docs updated
digi604 authored
195 try:
196 app_name = page.get_application_urls(fallback=False)
197 except Title.DoesNotExist:
198 app_name = None
fc35b42 @chrisglass Added comments to code (!) and generally tweaked readability (because it...
chrisglass authored
199 if app_name: # it means it is an apphook
4e63a49 @samluescher Backwards-compatibility fix for new class-based apphooks
samluescher authored
200 app = apphook_pool.get_apphook(app_name)
6967eea @digi604 apphooks working, nav extenders as well
digi604 authored
201 for menu in app.menus:
202 extenders.append(menu.__name__)
fc35b42 @chrisglass Added comments to code (!) and generally tweaked readability (because it...
chrisglass authored
203
6967eea @digi604 apphooks working, nav extenders as well
digi604 authored
204 if extenders:
205 attr['navigation_extenders'] = extenders
fc35b42 @chrisglass Added comments to code (!) and generally tweaked readability (because it...
chrisglass authored
206
207 # Do we have a redirectURL?
208 attr['redirect_url'] = page.get_redirect() # save redirect URL if any
209
210 # Now finally, build the NavigationNode object and return it.
1641218 @chrisglass Trivial changes:
chrisglass authored
211 ret_node = NavigationNode(
ba6ca93 @digi604 fixed testsuite and even reduced 2 queries .. yehaa
digi604 authored
212 page.get_menu_title(),
213 page.get_absolute_url(),
214 page.pk,
215 parent_id,
216 attr=attr,
217 visible=page.in_navigation,
218 )
1641218 @chrisglass Trivial changes:
chrisglass authored
219 return ret_node
38225bb @digi604 testsuite working again
digi604 authored
220
589de2c @digi604 some start of the menu discover infrastructure
digi604 authored
221 class CMSMenu(Menu):
222
223 def get_nodes(self, request):
224 page_queryset = get_page_queryset(request)
225 site = Site.objects.get_current()
226 lang = get_language_from_request(request)
fc35b42 @chrisglass Added comments to code (!) and generally tweaked readability (because it...
chrisglass authored
227
589de2c @digi604 some start of the menu discover infrastructure
digi604 authored
228 filters = {
229 'site':site,
230 }
fc35b42 @chrisglass Added comments to code (!) and generally tweaked readability (because it...
chrisglass authored
231
589de2c @digi604 some start of the menu discover infrastructure
digi604 authored
232 if settings.CMS_HIDE_UNTRANSLATED:
233 filters['title_set__language'] = lang
fc35b42 @chrisglass Added comments to code (!) and generally tweaked readability (because it...
chrisglass authored
234
922fc92 @stefanfoulis fixes #385: "too many values to unpack" error from cms/menu.py
stefanfoulis authored
235 pages = page_queryset.published().filter(**filters).order_by("tree_id", "lft")
fc35b42 @chrisglass Added comments to code (!) and generally tweaked readability (because it...
chrisglass authored
236
589de2c @digi604 some start of the menu discover infrastructure
digi604 authored
237 ids = []
6e71206 @digi604 show menu working. marking of nodes working. modifiers working. cutlevel...
digi604 authored
238 nodes = []
2d19d5c @digi604 all tests pass, nav extenders fully working now
digi604 authored
239 first = True
240 home_cut = False
241 home_children = []
ba6ca93 @digi604 fixed testsuite and even reduced 2 queries .. yehaa
digi604 authored
242 home = None
fd25f65 @jezdez Added can_view permission and re-enabled permissions caching again.
jezdez authored
243 actual_pages = []
6be7842 @ojii Improved menu building by getting all view permissions at once for all p...
ojii authored
244
245 # cache view perms
d7aa9c8 @ojii Drastically improved coverage of cms.menu.get_visible_pages and fixed so...
ojii authored
246 visible_pages = get_visible_pages(request, pages, site)
6be7842 @ojii Improved menu building by getting all view permissions at once for all p...
ojii authored
247 for page in pages:
fc35b42 @chrisglass Added comments to code (!) and generally tweaked readability (because it...
chrisglass authored
248 # Pages are ordered by tree_id, therefore the first page is the root
249 # of the page tree (a.k.a "home")
6be7842 @ojii Improved menu building by getting all view permissions at once for all p...
ojii authored
250 if page.pk not in visible_pages:
fd25f65 @jezdez Added can_view permission and re-enabled permissions caching again.
jezdez authored
251 # Don't include pages the user doesn't have access to
252 continue
ba6ca93 @digi604 fixed testsuite and even reduced 2 queries .. yehaa
digi604 authored
253 if not home:
254 home = page
255 page.home_pk_cache = home.pk
256 if first and page.pk != home.pk:
257 home_cut = True
258 if (page.parent_id == home.pk or page.parent_id in home_children) and home_cut:
259 home_children.append(page.pk)
260 if (page.pk == home.pk and home.in_navigation) or page.pk != home.pk:
261 first = False
589de2c @digi604 some start of the menu discover infrastructure
digi604 authored
262 ids.append(page.id)
fd25f65 @jezdez Added can_view permission and re-enabled permissions caching again.
jezdez authored
263 actual_pages.append(page)
264
589de2c @digi604 some start of the menu discover infrastructure
digi604 authored
265 titles = list(get_title_queryset(request).filter(page__in=ids, language=lang))
fd25f65 @jezdez Added can_view permission and re-enabled permissions caching again.
jezdez authored
266 for page in actual_pages: # add the title and slugs and some meta data
589de2c @digi604 some start of the menu discover infrastructure
digi604 authored
267 for title in titles:
268 if title.page_id == page.pk:
269 if not hasattr(page, "title_cache"):
270 page.title_cache = {}
271 page.title_cache[title.language] = title
38225bb @digi604 testsuite working again
digi604 authored
272 nodes.append(page_to_node(page, home, home_cut))
589de2c @digi604 some start of the menu discover infrastructure
digi604 authored
273 ids.remove(page.pk)
0ea37ba @jezdez A bit of cleanup (PEP8, consistency, dead code).
jezdez authored
274
589de2c @digi604 some start of the menu discover infrastructure
digi604 authored
275 if ids: # get fallback languages
276 fallbacks = get_fallback_languages(lang)
277 for l in fallbacks:
278 titles = list(get_title_queryset(request).filter(page__in=ids, language=l))
279 for title in titles:
fd25f65 @jezdez Added can_view permission and re-enabled permissions caching again.
jezdez authored
280 for page in actual_pages: # add the title and slugs and some meta data
589de2c @digi604 some start of the menu discover infrastructure
digi604 authored
281 if title.page_id == page.pk:
282 if not hasattr(page, "title_cache"):
283 page.title_cache = {}
284 page.title_cache[title.language] = title
38225bb @digi604 testsuite working again
digi604 authored
285 nodes.append(page_to_node(page, home, home_cut))
589de2c @digi604 some start of the menu discover infrastructure
digi604 authored
286 ids.remove(page.pk)
287 break
288 if not ids:
289 break
38225bb @digi604 testsuite working again
digi604 authored
290 return nodes
1b16cd4 @digi604 monster commit for menu refactor
digi604 authored
291 menu_pool.register_menu(CMSMenu)
292
293 class NavExtender(Modifier):
1641218 @chrisglass Trivial changes:
chrisglass authored
294 def modify(self, request, nodes, namespace, root_id, post_cut, breadcrumb):
bda49b2 @digi604 menu_levels working. nav-extenders correctly hiding if not assigned
digi604 authored
295 if post_cut:
296 return nodes
297 exts = []
298 # rearrange the parent relations
ba6ca93 @digi604 fixed testsuite and even reduced 2 queries .. yehaa
digi604 authored
299 home = None
1b16cd4 @digi604 monster commit for menu refactor
digi604 authored
300 for node in nodes:
ba6ca93 @digi604 fixed testsuite and even reduced 2 queries .. yehaa
digi604 authored
301 if node.attr.get("is_home", False):
302 home = node
6967eea @digi604 apphooks working, nav extenders as well
digi604 authored
303 extenders = node.attr.get("navigation_extenders", None)
304 if extenders:
305 for ext in extenders:
306 if not ext in exts:
307 exts.append(ext)
308 for n in nodes:
ba6ca93 @digi604 fixed testsuite and even reduced 2 queries .. yehaa
digi604 authored
309 if n.namespace == ext and not n.parent_id:# if home has nav extenders but home is not visible
310 if node.attr.get("is_home", False) and not node.visible:
311 n.parent_id = None
312 n.parent_namespace = None
313 n.parent = None
314 else:
315 n.parent_id = node.id
316 n.parent_namespace = node.namespace
317 n.parent = node
318 node.children.append(n)
bda49b2 @digi604 menu_levels working. nav-extenders correctly hiding if not assigned
digi604 authored
319 removed = []
320 # find all not assigned nodes
321 for menu in menu_pool.menus.items():
38225bb @digi604 testsuite working again
digi604 authored
322 if hasattr(menu[1], 'cms_enabled') and menu[1].cms_enabled and not menu[0] in exts:
bda49b2 @digi604 menu_levels working. nav-extenders correctly hiding if not assigned
digi604 authored
323 for node in nodes:
324 if node.namespace == menu[0]:
325 removed.append(node)
ba6ca93 @digi604 fixed testsuite and even reduced 2 queries .. yehaa
digi604 authored
326 if breadcrumb:
38225bb @digi604 testsuite working again
digi604 authored
327 # if breadcrumb and home not in navigation add node
ba6ca93 @digi604 fixed testsuite and even reduced 2 queries .. yehaa
digi604 authored
328 if breadcrumb and home and not home.visible:
329 home.visible = True
38225bb @digi604 testsuite working again
digi604 authored
330 if request.path == home.get_absolute_url():
331 home.selected = True
332 else:
333 home.selected = False
bda49b2 @digi604 menu_levels working. nav-extenders correctly hiding if not assigned
digi604 authored
334 # remove all nodes that are nav_extenders and not assigned
335 for node in removed:
336 nodes.remove(node)
38225bb @digi604 testsuite working again
digi604 authored
337 return nodes
338 menu_pool.register_modifier(NavExtender)
339
340
341 class SoftRootCutter(Modifier):
9d0323a @ojii Fixed issue 662, no idea if this is a valid fix but wtf are soft roots a...
ojii authored
342 """
bb7633f @ojii Fixes #1039
ojii authored
343 Ask evildmp/superdmp if you don't understand softroots!
344
345 Softroot description from the docs:
346
347 A soft root is a page that acts as the root for a menu navigation tree.
348
349 Typically, this will be a page that is the root of a significant new
350 section on your site.
351
352 When the soft root feature is enabled, the navigation menu for any page
353 will start at the nearest soft root, rather than at the real root of
354 the site’s page hierarchy.
355
356 This feature is useful when your site has deep page hierarchies (and
357 therefore multiple levels in its navigation trees). In such a case, you
358 usually don’t want to present site visitors with deep menus of nested
359 items.
360
a5a7092 @FrankBie2 code cleanup
FrankBie2 authored
361 For example, you’re on the page -Introduction to Bleeding-?, so the menu
bb7633f @ojii Fixes #1039
ojii authored
362 might look like this:
363
364 School of Medicine
365 Medical Education
366 Departments
367 Department of Lorem Ipsum
368 Department of Donec Imperdiet
369 Department of Cras Eros
370 Department of Mediaeval Surgery
371 Theory
372 Cures
373 Bleeding
374 Introduction to Bleeding <this is the current page>
375 Bleeding - the scientific evidence
376 Cleaning up the mess
377 Cupping
378 Leaches
379 Maggots
380 Techniques
381 Instruments
382 Department of Curabitur a Purus
383 Department of Sed Accumsan
384 Department of Etiam
385 Research
386 Administration
387 Contact us
388 Impressum
389
390 which is frankly overwhelming.
391
a5a7092 @FrankBie2 code cleanup
FrankBie2 authored
392 By making -Department of Mediaeval Surgery-? a soft root, the menu
bb7633f @ojii Fixes #1039
ojii authored
393 becomes much more manageable:
394
395 Department of Mediaeval Surgery
396 Theory
397 Cures
398 Bleeding
399 Introduction to Bleeding <current page>
400 Bleeding - the scientific evidence
401 Cleaning up the mess
402 Cupping
403 Leaches
404 Maggots
405 Techniques
406 Instruments
9d0323a @ojii Fixed issue 662, no idea if this is a valid fix but wtf are soft roots a...
ojii authored
407 """
1641218 @chrisglass Trivial changes:
chrisglass authored
408 def modify(self, request, nodes, namespace, root_id, post_cut, breadcrumb):
9d0323a @ojii Fixed issue 662, no idea if this is a valid fix but wtf are soft roots a...
ojii authored
409 # only apply this modifier if we're pre-cut (since what we do is cut)
65331d8 @digi604 softroots working
digi604 authored
410 if post_cut or not settings.CMS_SOFTROOT:
38225bb @digi604 testsuite working again
digi604 authored
411 return nodes
412 selected = None
65331d8 @digi604 softroots working
digi604 authored
413 root_nodes = []
9d0323a @ojii Fixed issue 662, no idea if this is a valid fix but wtf are soft roots a...
ojii authored
414 # find the selected node as well as all the root nodes
38225bb @digi604 testsuite working again
digi604 authored
415 for node in nodes:
416 if node.selected:
417 selected = node
65331d8 @digi604 softroots working
digi604 authored
418 if not node.parent:
419 root_nodes.append(node)
420
9d0323a @ojii Fixed issue 662, no idea if this is a valid fix but wtf are soft roots a...
ojii authored
421 # if we found a selected ...
38225bb @digi604 testsuite working again
digi604 authored
422 if selected:
9d0323a @ojii Fixed issue 662, no idea if this is a valid fix but wtf are soft roots a...
ojii authored
423 # and the selected is a softroot
38225bb @digi604 testsuite working again
digi604 authored
424 if selected.attr.get("soft_root", False):
9d0323a @ojii Fixed issue 662, no idea if this is a valid fix but wtf are soft roots a...
ojii authored
425 # get it's descendants
65331d8 @digi604 softroots working
digi604 authored
426 nodes = selected.get_descendants()
9d0323a @ojii Fixed issue 662, no idea if this is a valid fix but wtf are soft roots a...
ojii authored
427 # remove the link to parent
65331d8 @digi604 softroots working
digi604 authored
428 selected.parent = None
9d0323a @ojii Fixed issue 662, no idea if this is a valid fix but wtf are soft roots a...
ojii authored
429 # make the selected page the root in the menu
65331d8 @digi604 softroots working
digi604 authored
430 nodes = [selected] + nodes
38225bb @digi604 testsuite working again
digi604 authored
431 else:
9d0323a @ojii Fixed issue 662, no idea if this is a valid fix but wtf are soft roots a...
ojii authored
432 # if it's not a soft root, walk ancestors (upwards!)
e0a822e @ojii some progress in digging into 662
ojii authored
433 nodes = self.find_ancestors_and_remove_children(selected, nodes)
bb7633f @ojii Fixes #1039
ojii authored
434 return nodes
38225bb @digi604 testsuite working again
digi604 authored
435
e0a822e @ojii some progress in digging into 662
ojii authored
436 def find_and_remove_children(self, node, nodes):
38225bb @digi604 testsuite working again
digi604 authored
437 for n in node.children:
438 if n.attr.get("soft_root", False):
439 self.remove_children(n, nodes)
440 return nodes
441
442 def remove_children(self, node, nodes):
443 for n in node.children:
444 nodes.remove(n)
445 self.remove_children(n, nodes)
446 node.children = []
447
e0a822e @ojii some progress in digging into 662
ojii authored
448 def find_ancestors_and_remove_children(self, node, nodes):
9d0323a @ojii Fixed issue 662, no idea if this is a valid fix but wtf are soft roots a...
ojii authored
449 """
450 Check ancestors of node for soft roots
451 """
65331d8 @digi604 softroots working
digi604 authored
452 if node.parent:
453 if node.parent.attr.get("soft_root", False):
454 nodes = node.parent.get_descendants()
455 node.parent.parent = None
456 nodes = [node.parent] + nodes
457 else:
e0a822e @ojii some progress in digging into 662
ojii authored
458 nodes = self.find_ancestors_and_remove_children(node.parent, nodes)
65331d8 @digi604 softroots working
digi604 authored
459 else:
460 for n in nodes:
461 if n != node and not n.parent:
e0a822e @ojii some progress in digging into 662
ojii authored
462 self.find_and_remove_children(n, nodes)
38225bb @digi604 testsuite working again
digi604 authored
463 for n in node.children:
65331d8 @digi604 softroots working
digi604 authored
464 if n != node:
e0a822e @ojii some progress in digging into 662
ojii authored
465 self.find_and_remove_children(n, nodes)
38225bb @digi604 testsuite working again
digi604 authored
466 return nodes
467
26c58a1 @tonnzor Now direct links are used for items that used redirection
tonnzor authored
468 menu_pool.register_modifier(SoftRootCutter)
Something went wrong with that request. Please try again.