Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

monster commit for menu refactor

  • Loading branch information...
commit 1b16cd4322c032441858af23a35ed87ceb223f06 1 parent aeccf5b
@digi604 digi604 authored
View
5 cms/app_base.py
@@ -0,0 +1,5 @@
+
+class CMSApp(object):
+ name = None
+ urls = None
+ menus = []
View
35 cms/apphook_pool.py
@@ -0,0 +1,35 @@
+from django.conf import settings
+from cms.exceptions import AppAllreadyRegistered
+
+class ApphookPool(object):
+ def __init__(self):
+ self.apps = {}
+ self.discovered = False
+
+ def discover_apps(self):
+ if self.discovered:
+ return
+ #import all the modules
+ for app in settings.INSTALLED_APPS:
+ __import__(app, {}, {}, ['cms_apps'])
+ self.discovered = True
+
+ def clear(self):
+ self.apps = {}
+ self.discovered = False
+
+ def register(self, app):
+ from cms.app_base import CMSApp
+ assert issubclass(app, CMSApp)
+ if app.__name__ in self.apps.keys():
+ raise AppAllreadyRegistered, "[%s] an cms app with this name is already registered" % app.__name__
+ self.apps[app.__name__] = app
+
+ def get_apphooks(self):
+ hooks = []
+ for app_name in self.apps.keys():
+ app = self.apps[app_name]
+ hooks.append()
+
+
+apphook_pool = ApphookPool()
View
3  cms/exceptions.py
@@ -1,6 +1,9 @@
class PluginAllreadyRegistered(Exception):
pass
+class AppAllreadyRegistered(Exception):
+ pass
+
class NotImplemented(Exception):
pass
View
30 cms/menu.py
@@ -1,5 +1,5 @@
from menus.menu_pool import menu_pool
-from menus.base import Menu, NavigationNode
+from menus.base import Menu, NavigationNode, Modifier
from cms.utils import get_language_from_request
from cms.utils.moderator import get_page_queryset, get_title_queryset
from django.conf import settings
@@ -50,8 +50,30 @@ def get_nodes(self, request):
return nodes
def page_to_node(self, page):
- attr = {}
- n = NavigationNode(page.get_menu_title(), page.get_absolute_url(), "cms", page.pk, page.parent_id, "cms", attr, page.soft_root, page.login_required, reverse_id=page.reverse_id)
+ attr = {'navigation_extenders':page.navigation_extenders}
+ n = NavigationNode(page.get_menu_title(),
+ page.get_absolute_url(),
+ page.pk, page.parent_id,
+ attr=attr,
+ softroot=page.soft_root,
+ auth_required=page.login_required,
+ reverse_id=page.reverse_id)
return n
-menu_pool.register_menu(CMSMenu, "main")
+menu_pool.register_menu(CMSMenu)
+
+
+class NavExtender(Modifier):
+ def modify(self, request, nodes, namespace, id, post_cut):
+ copy = list(nodes)
+ for node in nodes:
+ ext = node.attr.get("navigation_extenders", None)
+ if ext:
+ for n in copy:
+ if n.namespace == ext and not n.parent_id:
+ n.parent_id = node.id
+ n.parent_namespace = node.namespace
+ n.parent = node
+ return nodes
+
+menu_pool.register_modifier(NavExtender)
View
1  cms/models/fixtures/test_navextender.json
@@ -1 +0,0 @@
-[{"pk": 7, "model": "cms.page", "fields": {"rght": 12, "navigation_extenders": null, "site": 1, "creation_date": "2009-12-23 14:40:59", "lft": 1, "in_navigation": true, "reverse_id": null, "login_required": false, "created_by": "admin", "publication_end_date": null, "moderator_state": 10, "template": "index.html", "tree_id": 1, "parent": null, "publisher_state": 1, "soft_root": false, "menu_login_required": false, "publication_date": "2009-12-23 14:41:10", "publisher_public": 8, "level": 0, "changed_by": "admin", "publisher_is_draft": true, "published": true}}, {"pk": 9, "model": "cms.page", "fields": {"rght": 3, "navigation_extenders": "cms.tests.util.menu_extender.get_nodes", "site": 1, "creation_date": "2009-12-23 14:41:32", "lft": 2, "in_navigation": true, "reverse_id": null, "login_required": false, "created_by": "admin", "publication_end_date": null, "moderator_state": 10, "template": "INHERIT", "tree_id": 1, "parent": 7, "publisher_state": 1, "soft_root": false, "menu_login_required": false, "publication_date": "2009-12-23 14:41:51", "publisher_public": 10, "level": 1, "changed_by": "admin", "publisher_is_draft": true, "published": true}}, {"pk": 11, "model": "cms.page", "fields": {"rght": 11, "navigation_extenders": null, "site": 1, "creation_date": "2009-12-23 14:43:47", "lft": 4, "in_navigation": true, "reverse_id": null, "login_required": false, "created_by": "admin", "publication_end_date": null, "moderator_state": 10, "template": "INHERIT", "tree_id": 1, "parent": 7, "publisher_state": 1, "soft_root": false, "menu_login_required": false, "publication_date": "2009-12-23 14:44:33", "publisher_public": 15, "level": 1, "changed_by": "admin", "publisher_is_draft": true, "published": true}}, {"pk": 12, "model": "cms.page", "fields": {"rght": 6, "navigation_extenders": null, "site": 1, "creation_date": "2009-12-23 14:43:56", "lft": 5, "in_navigation": true, "reverse_id": null, "login_required": false, "created_by": "admin", "publication_end_date": null, "moderator_state": 10, "template": "INHERIT", "tree_id": 1, "parent": 11, "publisher_state": 1, "soft_root": false, "menu_login_required": false, "publication_date": "2009-12-23 14:44:34", "publisher_public": 16, "level": 2, "changed_by": "admin", "publisher_is_draft": true, "published": true}}, {"pk": 13, "model": "cms.page", "fields": {"rght": 10, "navigation_extenders": null, "site": 1, "creation_date": "2009-12-23 14:44:07", "lft": 7, "in_navigation": true, "reverse_id": null, "login_required": false, "created_by": "admin", "publication_end_date": null, "moderator_state": 10, "template": "INHERIT", "tree_id": 1, "parent": 11, "publisher_state": 1, "soft_root": false, "menu_login_required": false, "publication_date": "2009-12-23 14:44:35", "publisher_public": 17, "level": 2, "changed_by": "admin", "publisher_is_draft": true, "published": true}}, {"pk": 14, "model": "cms.page", "fields": {"rght": 9, "navigation_extenders": null, "site": 1, "creation_date": "2009-12-23 14:44:19", "lft": 8, "in_navigation": true, "reverse_id": null, "login_required": false, "created_by": "admin", "publication_end_date": null, "moderator_state": 10, "template": "INHERIT", "tree_id": 1, "parent": 13, "publisher_state": 1, "soft_root": false, "menu_login_required": false, "publication_date": "2009-12-23 14:44:37", "publisher_public": 18, "level": 3, "changed_by": "admin", "publisher_is_draft": true, "published": true}}, {"pk": 8, "model": "cms.page", "fields": {"rght": 12, "navigation_extenders": null, "site": 1, "creation_date": "2009-12-23 14:40:59", "lft": 1, "in_navigation": true, "reverse_id": null, "login_required": false, "created_by": "admin", "publication_end_date": null, "moderator_state": 1, "template": "index.html", "tree_id": 2, "parent": null, "publisher_state": 0, "soft_root": false, "menu_login_required": false, "publication_date": "2009-12-23 14:41:10", "publisher_public": null, "level": 0, "changed_by": "admin", "publisher_is_draft": false, "published": true}}, {"pk": 10, "model": "cms.page", "fields": {"rght": 3, "navigation_extenders": "cms.tests.util.menu_extender.get_nodes", "site": 1, "creation_date": "2009-12-23 14:41:32", "lft": 2, "in_navigation": true, "reverse_id": null, "login_required": false, "created_by": "admin", "publication_end_date": null, "moderator_state": 1, "template": "INHERIT", "tree_id": 2, "parent": 8, "publisher_state": 0, "soft_root": false, "menu_login_required": false, "publication_date": "2009-12-23 14:41:51", "publisher_public": null, "level": 1, "changed_by": "admin", "publisher_is_draft": false, "published": true}}, {"pk": 15, "model": "cms.page", "fields": {"rght": 11, "navigation_extenders": null, "site": 1, "creation_date": "2009-12-23 14:43:47", "lft": 4, "in_navigation": true, "reverse_id": null, "login_required": false, "created_by": "admin", "publication_end_date": null, "moderator_state": 1, "template": "INHERIT", "tree_id": 2, "parent": 8, "publisher_state": 0, "soft_root": false, "menu_login_required": false, "publication_date": "2009-12-23 14:44:33", "publisher_public": null, "level": 1, "changed_by": "admin", "publisher_is_draft": false, "published": true}}, {"pk": 16, "model": "cms.page", "fields": {"rght": 6, "navigation_extenders": null, "site": 1, "creation_date": "2009-12-23 14:43:56", "lft": 5, "in_navigation": true, "reverse_id": null, "login_required": false, "created_by": "admin", "publication_end_date": null, "moderator_state": 1, "template": "INHERIT", "tree_id": 2, "parent": 15, "publisher_state": 0, "soft_root": false, "menu_login_required": false, "publication_date": "2009-12-23 14:44:34", "publisher_public": null, "level": 2, "changed_by": "admin", "publisher_is_draft": false, "published": true}}, {"pk": 17, "model": "cms.page", "fields": {"rght": 10, "navigation_extenders": null, "site": 1, "creation_date": "2009-12-23 14:44:07", "lft": 7, "in_navigation": true, "reverse_id": null, "login_required": false, "created_by": "admin", "publication_end_date": null, "moderator_state": 1, "template": "INHERIT", "tree_id": 2, "parent": 15, "publisher_state": 0, "soft_root": false, "menu_login_required": false, "publication_date": "2009-12-23 14:44:35", "publisher_public": null, "level": 2, "changed_by": "admin", "publisher_is_draft": false, "published": true}}, {"pk": 18, "model": "cms.page", "fields": {"rght": 9, "navigation_extenders": null, "site": 1, "creation_date": "2009-12-23 14:44:19", "lft": 8, "in_navigation": true, "reverse_id": null, "login_required": false, "created_by": "admin", "publication_end_date": null, "moderator_state": 1, "template": "INHERIT", "tree_id": 2, "parent": 17, "publisher_state": 0, "soft_root": false, "menu_login_required": false, "publication_date": "2009-12-23 14:44:37", "publisher_public": null, "level": 3, "changed_by": "admin", "publisher_is_draft": false, "published": true}}, {"pk": 18, "model": "cms.pagemoderatorstate", "fields": {"action": "ADD", "message": "", "created": "2009-12-23 14:41:10", "page": 8, "user": 1}}, {"pk": 19, "model": "cms.pagemoderatorstate", "fields": {"action": "PUB", "message": "", "created": "2009-12-23 14:41:10", "page": 8, "user": 1}}, {"pk": 22, "model": "cms.pagemoderatorstate", "fields": {"action": "ADD", "message": "", "created": "2009-12-23 14:41:51", "page": 10, "user": 1}}, {"pk": 23, "model": "cms.pagemoderatorstate", "fields": {"action": "PUB", "message": "", "created": "2009-12-23 14:41:51", "page": 10, "user": 1}}, {"pk": 29, "model": "cms.pagemoderatorstate", "fields": {"action": "ADD", "message": "", "created": "2009-12-23 14:44:33", "page": 15, "user": 1}}, {"pk": 30, "model": "cms.pagemoderatorstate", "fields": {"action": "PUB", "message": "", "created": "2009-12-23 14:44:33", "page": 15, "user": 1}}, {"pk": 32, "model": "cms.pagemoderatorstate", "fields": {"action": "ADD", "message": "", "created": "2009-12-23 14:44:34", "page": 16, "user": 1}}, {"pk": 33, "model": "cms.pagemoderatorstate", "fields": {"action": "PUB", "message": "", "created": "2009-12-23 14:44:34", "page": 16, "user": 1}}, {"pk": 35, "model": "cms.pagemoderatorstate", "fields": {"action": "ADD", "message": "", "created": "2009-12-23 14:44:35", "page": 17, "user": 1}}, {"pk": 36, "model": "cms.pagemoderatorstate", "fields": {"action": "PUB", "message": "", "created": "2009-12-23 14:44:35", "page": 17, "user": 1}}, {"pk": 38, "model": "cms.pagemoderatorstate", "fields": {"action": "ADD", "message": "", "created": "2009-12-23 14:44:37", "page": 18, "user": 1}}, {"pk": 39, "model": "cms.pagemoderatorstate", "fields": {"action": "PUB", "message": "", "created": "2009-12-23 14:44:37", "page": 18, "user": 1}}, {"pk": 18, "model": "cms.title", "fields": {"publisher_public": null, "menu_title": null, "meta_keywords": null, "page_title": null, "language": "de", "title": "Home", "has_url_overwrite": false, "application_urls": null, "creation_date": "2009-12-23 14:40:59", "publisher_is_draft": false, "publisher_state": 0, "path": "home", "meta_description": null, "slug": "home", "redirect": null, "page": 8}}, {"pk": 17, "model": "cms.title", "fields": {"publisher_public": 18, "menu_title": null, "meta_keywords": null, "page_title": null, "language": "de", "title": "Home", "has_url_overwrite": false, "application_urls": null, "creation_date": "2009-12-23 14:40:59", "publisher_is_draft": true, "publisher_state": 0, "path": "home", "meta_description": null, "slug": "home", "redirect": null, "page": 7}}, {"pk": 20, "model": "cms.title", "fields": {"publisher_public": null, "menu_title": "", "meta_keywords": "", "page_title": "", "language": "de", "title": "Extended Page", "has_url_overwrite": false, "application_urls": "sampleapp.urlstwo", "creation_date": "2009-12-23 14:41:32", "publisher_is_draft": false, "publisher_state": 0, "path": "home/extended-page", "meta_description": "", "slug": "extended-page", "redirect": "", "page": 10}}, {"pk": 19, "model": "cms.title", "fields": {"publisher_public": 20, "menu_title": "", "meta_keywords": "", "page_title": "", "language": "de", "title": "Extended Page", "has_url_overwrite": false, "application_urls": "sampleapp.urlstwo", "creation_date": "2009-12-23 14:41:32", "publisher_is_draft": true, "publisher_state": 0, "path": "home/extended-page", "meta_description": "", "slug": "extended-page", "redirect": "", "page": 9}}, {"pk": 25, "model": "cms.title", "fields": {"publisher_public": null, "menu_title": null, "meta_keywords": null, "page_title": null, "language": "de", "title": "Normal Page", "has_url_overwrite": false, "application_urls": null, "creation_date": "2009-12-23 14:43:47", "publisher_is_draft": false, "publisher_state": 0, "path": "home/normal-page", "meta_description": null, "slug": "normal-page", "redirect": null, "page": 15}}, {"pk": 21, "model": "cms.title", "fields": {"publisher_public": 25, "menu_title": null, "meta_keywords": null, "page_title": null, "language": "de", "title": "Normal Page", "has_url_overwrite": false, "application_urls": null, "creation_date": "2009-12-23 14:43:47", "publisher_is_draft": true, "publisher_state": 0, "path": "home/normal-page", "meta_description": null, "slug": "normal-page", "redirect": null, "page": 11}}, {"pk": 26, "model": "cms.title", "fields": {"publisher_public": null, "menu_title": null, "meta_keywords": null, "page_title": null, "language": "de", "title": "One", "has_url_overwrite": false, "application_urls": null, "creation_date": "2009-12-23 14:43:56", "publisher_is_draft": false, "publisher_state": 0, "path": "home/normal-page/one", "meta_description": null, "slug": "one", "redirect": null, "page": 16}}, {"pk": 22, "model": "cms.title", "fields": {"publisher_public": 26, "menu_title": null, "meta_keywords": null, "page_title": null, "language": "de", "title": "One", "has_url_overwrite": false, "application_urls": null, "creation_date": "2009-12-23 14:43:56", "publisher_is_draft": true, "publisher_state": 0, "path": "home/normal-page/one", "meta_description": null, "slug": "one", "redirect": null, "page": 12}}, {"pk": 27, "model": "cms.title", "fields": {"publisher_public": null, "menu_title": null, "meta_keywords": null, "page_title": null, "language": "de", "title": "Two", "has_url_overwrite": false, "application_urls": null, "creation_date": "2009-12-23 14:44:07", "publisher_is_draft": false, "publisher_state": 0, "path": "home/normal-page/two", "meta_description": null, "slug": "two", "redirect": null, "page": 17}}, {"pk": 23, "model": "cms.title", "fields": {"publisher_public": 27, "menu_title": null, "meta_keywords": null, "page_title": null, "language": "de", "title": "Two", "has_url_overwrite": false, "application_urls": null, "creation_date": "2009-12-23 14:44:07", "publisher_is_draft": true, "publisher_state": 0, "path": "home/normal-page/two", "meta_description": null, "slug": "two", "redirect": null, "page": 13}}, {"pk": 28, "model": "cms.title", "fields": {"publisher_public": null, "menu_title": null, "meta_keywords": null, "page_title": null, "language": "de", "title": "Subpage", "has_url_overwrite": false, "application_urls": null, "creation_date": "2009-12-23 14:44:19", "publisher_is_draft": false, "publisher_state": 0, "path": "home/normal-page/two/subpage", "meta_description": null, "slug": "subpage", "redirect": null, "page": 18}}, {"pk": 24, "model": "cms.title", "fields": {"publisher_public": 28, "menu_title": null, "meta_keywords": null, "page_title": null, "language": "de", "title": "Subpage", "has_url_overwrite": false, "application_urls": null, "creation_date": "2009-12-23 14:44:19", "publisher_is_draft": true, "publisher_state": 0, "path": "home/normal-page/two/subpage", "meta_description": null, "slug": "subpage", "redirect": null, "page": 14}}]
View
5 cms/tests/apphooks.py
@@ -0,0 +1,5 @@
+'''
+Created on Jan 22, 2010
+
+@author: patricklauber
+'''
View
36 cms/tests/menu.py
@@ -1,10 +1,8 @@
# -*- coding: utf-8 -*-
from django.conf import settings
-from django.http import HttpRequest
-from django.template import TemplateDoesNotExist
from django.contrib.auth.models import User
-from cms.tests.base import CMSTestCase, URL_CMS_PAGE, URL_CMS_PAGE_ADD
-from cms.models import Page, Title
+from cms.tests.base import CMSTestCase
+from cms.models import Page
from cms.menu import CMSMenu
from menus.templatetags.menu_tags import show_menu, show_sub_menu,\
show_breadcrumb, language_chooser, page_language_url, show_menu_below_id
@@ -19,6 +17,11 @@ def setUp(self):
u.set_password("test")
u.save()
self.login_user(u)
+ self.old_menu = menu_pool.menus
+ menu_pool.menus = {'CMSMenu':self.old_menu['CMSMenu']}
+
+ def tearDown(self):
+ menu_pool.menus = self.old_menu
def create_some_nodes(self):
self.page1 = self.create_page(parent_page=None, published=True, in_navigation=True)
@@ -28,6 +31,7 @@ def create_some_nodes(self):
self.page5 = self.create_page(parent_page=self.page4, published=True, in_navigation=True)
def test_01_basic_cms_menu(self):
+ self.assertEqual(len(menu_pool.menus), 1)
self.create_some_nodes()
response = self.client.get("/")
self.assertEquals(response.status_code, 200)
@@ -153,7 +157,7 @@ def test_12_page_language_url(self):
self.assertEqual( url, "/%s%s" % (settings.LANGUAGES[0][0], self.page3.get_absolute_url()))
def test_13_show_menu_below_id(self):
- menu_pool.clean_nodes()
+ menu_pool.clear()
self.create_some_nodes()
page2 = Page.objects.get(pk=self.page2.pk)
page2.reverse_id = "hello"
@@ -165,4 +169,26 @@ def test_13_show_menu_below_id(self):
self.assertEqual(len(nodes), 1)
self.assertEqual(nodes[0].get_absolute_url(), self.page3.get_absolute_url())
+
+ def test_14_unpublished(self):
+ menu_pool.clear()
+ self.create_some_nodes()
+ page2 = Page.objects.get(pk=self.page2.pk)
+ page2.published = False
+ page2.save()
+ context = self.get_context()
+ nodes = show_menu(context)['children']
+ self.assertEqual(len(nodes), 2)
+ self.assertEqual(len(nodes[0].children), 0)
+
+ def test_15_home_not_in_menu(self):
+ menu_pool.clear()
+ self.create_some_nodes()
+ page1 = Page.objects.get(pk=self.page1.pk)
+ page1.in_navigation = False
+ page1.save()
+ context = self.get_context()
+ nodes = show_menu(context)['children']
+ self.assertEqual(len(nodes), 2)
+ self.assertEqual(nodes[0].get_absolute_url(), "/%s/" % self.page2.get_slug())
View
148 cms/tests/navextender.py
@@ -5,109 +5,71 @@
from django.core.handlers.wsgi import WSGIRequest
from django.contrib.sites.models import Site
from django.template.defaultfilters import slugify
-from django.test import TestCase
+from django.conf import settings
from cms.tests.base import CMSTestCase
+from cms.menu import CMSMenu
+from menus.menu_pool import menu_pool
+from cms.tests.util.menu_extender import TestMenu
class NavExtenderTestCase(CMSTestCase):
- fixtures = ['test_navextender', ]
- #urls = 'example.sampleapp.urlstwo'
-
- PK_ROOT = 8
- PK_NORMAL = 15
- PK_EXTENDED = 10
-
def setUp(self):
- self.context = self.get_context()
-
- def _prepage_page_pk(self, page_pk):
- self.context['request'].current_page = Page.objects.get(pk = page_pk)
- def test_submenu_root(self):
- """
- Checks if the submenu works correctly with root_page
- """
-
- self._prepage_page_pk(self.PK_ROOT)
- result = show_menu(self.context, 0, 100, 0, 1)
-
- # we expect page "Home" with attribute "childrens" containing two pages
- children = result['children']
- self.assertEqual(len(children), 1, 'Expecting only the root-page to be in children')
- p = children[0]
- self.assertEqual(p.pk, self.PK_ROOT, 'Expecting pk to be %s' % self.PK_ROOT)
-
- # checking childrens
- self.assertEqual(len(p.childrens), 2, 'Expecting two menu entries')
- self.assertEqual(p.childrens[0].pk, self.PK_EXTENDED)
- self.assertEqual(p.childrens[1].pk, self.PK_NORMAL)
+ settings.CMS_MODERATOR = False
+ u = User(username="test", is_staff = True, is_active = True, is_superuser = True)
+ u.set_password("test")
+ u.save()
+ self.login_user(u)
+ menu_pool.menus['TestMenu'] = TestMenu()
- # with no submenu entrie
- for child in p.childrens:
- self.assertEqual(len(child.childrens), 0, 'Expecting no submenu entries')
+ def tearDown(self):
+ del menu_pool.menus['TestMenu']
-
- def test_submenu_normal(self):
- """
- Checks the submenu for normal pages (without nav extenders)
- """
+ def create_some_nodes(self):
+ self.page1 = self.create_page(parent_page=None, published=True, in_navigation=True)
+ self.page2 = self.create_page(parent_page=self.page1, published=True, in_navigation=True)
+ self.page3 = self.create_page(parent_page=self.page2, published=True, in_navigation=True)
+ self.page4 = self.create_page(parent_page=None, published=True, in_navigation=True)
+ self.page5 = self.create_page(parent_page=self.page4, published=True, in_navigation=True)
- self._prepage_page_pk(self.PK_NORMAL)
- result = show_menu(self.context, 0, 100, 0, 1)
-
- children = result['children']
- self.assertEqual(len(children), 1, 'Expecting only the root-page to be in children')
- p = children[0]
- self.assertEqual(p.pk, self.PK_ROOT, 'Expecting pk to be %s' % self.PK_ROOT)
+ def test_01_menu_registration(self):
+ self.assertEqual(len(menu_pool.menus) >= 2, True)
- # checking childrens of root page
- self.assertEqual(len(p.childrens), 2, 'Expecting two menu entries')
- self.assertEqual(p.childrens[0].pk, self.PK_EXTENDED)
- self.assertEqual(p.childrens[1].pk, self.PK_NORMAL)
-
- # extended should have no children
- self.assertEqual(len(p.childrens[0].childrens), 0,
- 'Extended page\'s children should not be visible. %s' % self._string_result(result))
- self.assertEqual(len(p.childrens[1].childrens), 2, 'Children of normal page should be visible')
+ def test_02_extenders_on_root(self):
+ menu_pool.clear()
+ self.create_some_nodes()
+ page1 = Page.objects.get(pk=self.page1.pk)
+ page1.navigation_extenders = "TestMenu"
+ page1.save()
+ context = self.get_context()
+ nodes = show_menu(context)['children']
+ self.assertEqual(len(nodes), 2)
+ self.assertEqual(len(nodes[0].children), 4)
+ self.assertEqual(len(nodes[0].children[3].children), 1)
+ page1.in_navigation = False
+ page1.save()
+ nodes = show_menu(context)['children']
+ self.assertEqual(len(nodes), 6)
-
-
- def test_submenu_extended(self):
- """
- Checks the submenu of the extended page
- """
- self._prepage_page_pk(self.PK_EXTENDED)
- result = show_menu(self.context, 0, 100, 0, 1)
-
- children = result['children']
- self.assertEqual(len(children), 1, 'Expecting only the root-page to be in children')
- p = children[0]
- self.assertEqual(p.pk, self.PK_ROOT, 'Expecting pk to be %s' % self.PK_ROOT)
-
- # checking childrens of root page
- self.assertEqual(len(p.childrens), 2, 'Expecting two menu entries')
- self.assertEqual(p.childrens[0].pk, self.PK_EXTENDED)
- self.assertEqual(p.childrens[1].pk, self.PK_NORMAL)
-
- # extended should have no children
- self.assertEqual(len(p.childrens[0].childrens), 2,
- 'Extended page\'s children should be visible. %s' % self._string_result(result))
- self.assertEqual(len(p.childrens[1].childrens), 0, 'Children of normal page should not be visible')
+ def test_03_extenders_on_root_child(self):
+ menu_pool.clear()
+ self.create_some_nodes()
+ page4 = Page.objects.get(pk=self.page4.pk)
+ page4.navigation_extenders = "TestMenu"
+ page4.save()
+ context = self.get_context()
+ nodes = show_menu(context)['children']
+ self.assertEqual(len(nodes), 2)
+ self.assertEqual(len(nodes[1].children), 4)
- def _string_result(self, result):
- # check result
- retval = []
- retval.append("Got Result:")
- for c in result['children']:
- retval.append(self._string_page(c))
- return ' '.join(retval)
-
- def _string_page(self, page):
- retval = []
- # add pk to display
- #retval.append("%s, %s" % (repr(page), getattr(page, 'pk', 'NAVNODE')))
- retval.append("%s" % (repr(page),))
- for c in page.childrens:
- retval.append(self._string_page(c))
- return ' '.join(retval)
+ def test_04_extenders_on_child(self):
+ menu_pool.clear()
+ self.create_some_nodes()
+ page2 = Page.objects.get(pk=self.page2.pk)
+ page2.navigation_extenders = "TestMenu"
+ page2.save()
+ context = self.get_context()
+ nodes = show_menu(context)['children']
+ self.assertEqual(nodes, 2)
+ self.assertEqual(nodes[0].children, 5)
View
33 cms/tests/util/menu_extender.py
@@ -1,13 +1,22 @@
-from cms.utils.navigation import NavigationNode
-from django.core.urlresolvers import reverse
-from django.utils.translation import ugettext_lazy as _
+from menus.base import Menu, NavigationNode
+from menus.menu_pool import menu_pool
-def get_nodes(request):
- res = [] # result list
- n = NavigationNode(_('Sublevel'), 'sublevel')
- n2 = NavigationNode(_('Sublevel3'), 'sublevel3')
- n.childrens = [n2]
- res.append(n)
- n = NavigationNode(_('Sublevel 2'), 'sublevel2')
- res.append(n)
- return res
+
+class TestMenu(Menu):
+ cms_enabled = True
+ name = "Some name"
+ namespace = "test"
+
+ def get_nodes(self, request):
+ nodes = []
+ n = NavigationNode('sample root page', "/", 1)
+ n2 = NavigationNode('sample settings page', "/bye/", 2)
+ n3 = NavigationNode('sample account page', "/hello/", 3)
+ n4 = NavigationNode('sample my profile page', "/hello/world/", 4, 3)
+ nodes.append(n)
+ nodes.append(n2)
+ nodes.append(n3)
+ nodes.append(n4)
+ return nodes
+
+menu_pool.register_menu(TestMenu)
View
10 example/sampleapp/cms_app.py
@@ -0,0 +1,10 @@
+from cms.app_base import CMSApp
+from example.sampleapp.menu import StaticMenu, CategoryMenu
+from cms.apphook_pool import apphook_pool
+
+class SampleApp(CMSApp):
+ name = _("Sample App")
+ urls = "sampleapp.urls"
+ menus = [CategoryMenu, StaticMenu]
+
+apphook_pool.register(SampleApp)
View
20 example/sampleapp/menu.py
@@ -2,9 +2,11 @@
from example.sampleapp.models import Category
from django.core.urlresolvers import reverse
from menus.menu_pool import menu_pool
-
+from cms.app_base import CMSApp
+from django.utils.translation import ugettext_lazy as _
class CategoryMenu(Menu):
+
def get_nodes(self, request):
nodes = []
for cat in Category.objects.all():
@@ -14,14 +16,14 @@ def get_nodes(self, request):
menu_pool.register_menu(CategoryMenu)
-
class StaticMenu(Menu):
+
def get_nodes(self, request):
nodes = []
- n = NavigationNode(_('sample root page'), reverse('sample-root'), 1, "static")
- n2 = NavigationNode(_('sample settings page'), reverse('sample-settings'), 2, "static")
- n3 = NavigationNode(_('sample account page'), reverse('sample-account'), 3, "static")
- n4 = NavigationNode(_('sample my profile page'), reverse('sample-profile'), 4, "static", 3, "static")
+ n = NavigationNode(_('sample root page'), reverse('sample-root'), 1)
+ n2 = NavigationNode(_('sample settings page'), reverse('sample-settings'), 2)
+ n3 = NavigationNode(_('sample account page'), reverse('sample-account'), 3)
+ n4 = NavigationNode(_('sample my profile page'), reverse('sample-profile'), 4, 3)
nodes.append(n)
nodes.append(n2)
nodes.append(n3)
@@ -30,7 +32,5 @@ def get_nodes(self, request):
menu_pool.register_menu(StaticMenu)
-class SampleApp(CMSApp):
- name = _("Sample App")
- urls = "sampleapp.urls"
- menus = [CategoryMenu, StaticMenu]
+
+
View
34 example/sampleapp/menu_extender.py
@@ -1,34 +0,0 @@
-from cms.utils.navigation import NavigationNode
-from django.core.urlresolvers import reverse
-from django.utils.translation import ugettext_lazy as _
-
-def get_nodes(request):
- res = [] # result list
- lang = request.LANGUAGE_CODE
- n = NavigationNode(_('Sublevel'), reverse('%s:sample-app-sublevel' % lang))
- n2 = NavigationNode(_('Sublevel3'), reverse('%s:sample-app-sublevel3' % lang))
- n.childrens = [n2]
- res.append(n)
- n = NavigationNode(_('Sublevel 2'), reverse('%s:sample-app-sublevel2' % lang))
- res.append(n)
- return res
-
-
-from categories.models import Category
-
-def get_nodes(request):
- cats = list(Category.objects.all())
- res = []
- all_cats = cats[:]
- childs = []
- for cat in cats:
- if cat.parent_id:
- childs.append(cat)
- else:
- res.append(cat)
- for cat in all_cats:
- cat.childrens = []
- for child in childs:
- if child.parent_id == cat.pk:
- cat.childrens.append(child)
- return res
View
5 example/sampleapp/templates/sampleapp/category_view.html
@@ -0,0 +1,5 @@
+{% extends 'index.html' %}
+
+{% block content %}
+<h1>{{ category.get_title }}</h1>
+{% endblock %}
View
15 example/settings.py
@@ -119,13 +119,9 @@
'cms.plugins.inherit',
'mptt',
'reversion',
- 'example.categories',
+ 'example.sampleapp',
#'debug_toolbar',
'south',
- # sample application
- 'example.sampleapp',
- #'test_utils',
- #'store',
)
gettext = lambda s: s
@@ -153,10 +149,7 @@
('long-folder-long/long-template-name.html', gettext('long')),
)
-CMS_APPLICATIONS_URLS = (
- ('sampleapp.urls', 'Sample application'),
- ('sampleapp.urlstwo', 'Second sample application'),
-)
+
CMS_PLACEHOLDER_CONF = {
'right-column': {
@@ -180,10 +173,6 @@
},
}
-
-CMS_NAVIGATION_EXTENDERS = (('example.categories.navigation.get_nodes', 'Categories'),
- ('example.sampleapp.menu_extender.get_nodes', 'SampleApp Menu'),)
-
CMS_SOFTROOT = True
CMS_MODERATOR = True
CMS_PERMISSION = True
View
2  example/urls.py
@@ -10,8 +10,6 @@
#(r'^admin/(.*)', admin.site.root),
(r'^admin/', include(admin.site.urls)),
(r'^jsi18n/(?P<packages>\S+?)/$', 'django.views.i18n.javascript_catalog'),
- (r'^categories/', include('categories.urls')),
-
# just for testing - native way to sampleapp urls
# (r'^sampleapp-native/', include('sampleapp.urls')),
)
View
24 menus/base.py
@@ -1,7 +1,14 @@
+from django.core.exceptions import ValidationError
class Menu(object):
- nodes = []
+ name = None
+ cms_enabled = False
+ namespace = "main"
+
+ def __init__(self):
+ if self.cms_enabled and not self.name:
+ raise ValidationError("the menu %s is cms_enabled but has no name" % self.__class__.__name__)
def get_nodes(self, request):
"""
@@ -9,8 +16,6 @@ def get_nodes(self, request):
"""
raise NotImplementedError
-
-
class Modifier(object):
pre_cut = True
post_cut = False
@@ -21,14 +26,6 @@ def set_nodes(self, nodes):
def modify(self, request, nodes, namespace, id, post_cut):
pass
- def modify_all(self, request, nodes, namespace, id, post_cut):
- pass
-
- def remove_node(self, node):
- self.nodes.remove(node)
- if node.parent:
- node.parent.children.remove(node)
-
class NavigationNode(object):
title = None
url = None
@@ -45,13 +42,12 @@ class NavigationNode(object):
selected = False
- def __init__(self, title, url, namespace, id, parent_id=None, parent_namespace=None, attr=None, softroot=False, auth_required=False, required_group_id=None, reverse_id=None):
+ def __init__(self, title, url, id, parent_id=None, parent_namespace=None, attr=None, softroot=False, auth_required=False, required_group_id=None, reverse_id=None):
self.children = [] # do not touch
self.title = title
self.url = url
self.id = id
self.softroot = softroot
- self.namespace = namespace
self.parent_id = parent_id
self.parent_namespace = parent_namespace
self.auth_required = auth_required
@@ -61,7 +57,7 @@ def __init__(self, title, url, namespace, id, parent_id=None, parent_namespace=N
self.attr = attr
def __repr__(self):
- return "<Navigation Node: %s>" % self.title
+ return "<Navigation Node: %s>" % str(unicode(self.title))
def get_menu_title(self):
return self.title
View
29 menus/menu_pool.py
@@ -25,18 +25,25 @@ def discover_menus(self):
klass = getattr(module, class_name)
inst = klass()
self.modifiers.append(inst)
+ __import__("menus.modifiers",(),(),()) #register the modifiers
self.discovered = True
- def clean_nodes(self):
+ def clear(self):
self.nodes = {}
+ self.discovered = False
- def register_menu(self, menu, namespace):
+ def register_menu(self, menu):
from menus.base import Menu
assert issubclass(menu, Menu)
- if namespace in self.menus.keys():
- raise NamespaceAllreadyRegistered, "[%s] a menu namespace with this name is already registered" % namespace
- self.menus[namespace] = menu()
+ if menu.__name__ in self.menus.keys():
+ raise NamespaceAllreadyRegistered, "[%s] a menu with this name is already registered" % menu.__name__
+ self.menus[menu.__name__] = menu()
+
+ def register_modifier(self, modifier_class):
+ from menus.base import Modifier
+ assert issubclass(modifier_class, Modifier)
+
def _build_nodes(self, request, site_id):
lang = request.LANGUAGE_CODE
@@ -51,7 +58,11 @@ def _build_nodes(self, request, site_id):
nodes = self.menus[ns].get_nodes(request)
last = None
for node in nodes:
+ if not node.namespace:
+ node.namespace = ns
if node.parent_id:
+ if not node.parent_namespace:
+ node.parent_namespace = ns
found = False
if last:
n = last
@@ -70,7 +81,8 @@ def _build_nodes(self, request, site_id):
node.parent = n
found = True
if not found:
- raise NoParentFound, "No parent found for %s" % node.get_menu_title()
+ node.parent = None
+ continue
node.parent.children.append(node)
self.nodes[lang][site_id].append(node)
last = node
@@ -80,10 +92,7 @@ def _apply_modifiers(self, nodes, request, namespace, root_id):
nodes = self._mark_selected(request, nodes)
for inst in self.modifiers:
inst.set_nodes(nodes)
- inst.modify_all(request, nodes, namespace, root_id, False)
- for node in nodes:
- for inst in self.modifiers:
- inst.modify(request, node, namespace, root_id, False)
+ nodes = inst.modify(request, nodes, namespace, root_id, False)
return nodes
View
59 menus/modifiers.py
@@ -1,4 +1,5 @@
from menus.base import Modifier
+from menus.menu_pool import menu_pool
class Marker(Modifier):
"""
@@ -8,7 +9,7 @@ class Marker(Modifier):
descendants: descendant = True
ancestors: ancestor = True
"""
- def modify_all(self, request, nodes, namespace, root_id, post_cut):
+ def modify(self, request, nodes, namespace, root_id, post_cut):
selected = None
root_nodes = []
for node in nodes:
@@ -41,12 +42,14 @@ def modify_all(self, request, nodes, namespace, root_id, post_cut):
node.is_leaf_node = False
else:
node.is_leaf_node = True
+ return nodes
def mark_descendants(self, nodes):
for node in nodes:
node.descendant = True
self.mark_descendants(node.children)
+menu_pool.register_modifier(Marker)
class Level(Modifier):
"""
@@ -54,13 +57,21 @@ class Level(Modifier):
"""
post_cut = True
- def modify(self, request, node, namespace, root_id, post_cut):
- if not node.parent:
- if post_cut:
- node.menu_level = 0
+ def modify(self, request, nodes, namespace, root_id, post_cut):
+ print nodes
+ print "============="
+ for node in nodes:
+ if not node.parent:
+ print node
+ if post_cut:
+ node.menu_level = 0
+ else:
+ node.level = 0
+ self.mark_levels(node, post_cut)
else:
- node.level = 0
- self.mark_levels(node, post_cut)
+ print node
+ print 'parent', node.parent
+ return nodes
def mark_levels(self, node, post_cut):
@@ -71,24 +82,30 @@ def mark_levels(self, node, post_cut):
child.level = node.level + 1
self.mark_levels(child, post_cut)
+menu_pool.register_modifier(Level)
class LoginRequired(Modifier):
"""
Remove nodes that are login required or require a group
"""
- def modify(self, request, node, namespace, root_id, post_cut):
- good = False
- if node.auth_required and request.user.is_authenticated():
- good = True
- if node.required_group_id and request.user.is_authenticated():
- if not hasattr(request.user, "group_cache"):
- request.user.group_cache = request.user.groups.all()
+ def modify(self, request, nodes, namespace, root_id, post_cut):
+ final = []
+ for node in nodes:
good = False
- for group in request.user.group_cache:
- if group.pk == node.required_group_id:
- good = True
- break
- if good or (not node.auth_required and not node.required_group_id):
- return node
- self.remove_node(node)
+ if node.auth_required and request.user.is_authenticated():
+ good = True
+ if node.required_group_id and request.user.is_authenticated():
+ if not hasattr(request.user, "group_cache"):
+ request.user.group_cache = request.user.groups.all()
+ good = False
+ for group in request.user.group_cache:
+ if group.pk == node.required_group_id:
+ good = True
+ break
+ if good or (not node.auth_required and not node.required_group_id):
+ final.append(node)
+ return final
+
+menu_pool.register_modifier(LoginRequired)
+
View
2  menus/templatetags/menu_tags.py
@@ -25,6 +25,8 @@ def cut_levels(nodes, from_level, to_level, extra_inactive, extra_active):
for node in nodes:
if not node.parent and not node.ancestor and not node.selected:
cut_after(node, extra_inactive, removed)
+ if not hasattr(node, "level"):
+ print node
if node.level == from_level:
final.append(node)
if node.level > to_level and node.parent:
Please sign in to comment.
Something went wrong with that request. Please try again.