Skip to content
This repository
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 234 lines (210 sloc) 8.726 kb
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 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
# -*- coding: utf-8 -*-
from cms.models.titlemodels import Title
from django.conf import settings


def mark_descendants(nodes):
    for node in nodes:
        node.descendant = True
        mark_descendants(node.children)

def make_tree(items, levels, url, ancestors, descendants=False,
              current_level=0, to_levels=100, active_levels=0):
    from cms.models import Page # Probably avoids circular imports...
    """
Builds the tree which gets displayed in the CMSChangeList (in the admin
view, the nice Javascript tree of pages you get)
"""
    levels -= 1
    current_level += 1
    found = False
    for item in items:
        item.level = current_level
        if descendants and not found:
            item.descendant = True
        item.ancestors_ascending = ancestors
        if item.get_absolute_url() == url:
            item.selected = True
            item.descendant = False
            levels = active_levels
            descendants = True
            found = True
            last = None
            for anc in ancestors:
                if not isinstance(anc, Page) and last:
                    last = None
                    if hasattr(last, 'childrens'):
                        for child in last.childrens:
                            if isinstance(child, Page):
                                child.sibling = True
                else:
                    last = anc
                anc.ancestor = True
            if last:
                if hasattr(last, 'childrens'):
                    for child in last.childrens:
                        if isinstance(child, Page):
                            child.sibling = True
        elif found:
            item.sibling = True
        if levels == 0 and not hasattr(item, "ancestor" ) or item.level == to_levels or not hasattr(item, "childrens"):
            item.childrens = []
        else:
            make_tree(item.childrens, levels, url, ancestors+[item], descendants, current_level, to_levels, active_levels)
    if found:
        for item in items:
            if not hasattr(item, "selected"):
                item.sibling = True

def get_extended_navigation_nodes(request, levels, ancestors, current_level, to_levels, active_levels, mark_sibling, path):
    """
discovers all navigation nodes from navigation extenders
"""
    func_name = path.split(".")[-1]
    ext = __import__(".".join(path.split(".")[:-1]),(),(),(func_name,))
    func = getattr(ext, func_name)
    items = func(request)
    descendants = False
    for anc in ancestors:
        if hasattr(anc, 'selected'):
            if anc.selected:
                descendants = True
    if len(ancestors) and hasattr(ancestors[-1], 'ancestor'):
        make_tree(items, 100, request.path, ancestors, descendants, current_level, 100, active_levels)
    make_tree(items, levels, request.path, ancestors, descendants, current_level, to_levels, active_levels)
    if mark_sibling:
        for item in items:
            if not hasattr(item, "selected" ):
                item.sibling = True
    return items
    
def find_children(target, pages, levels=100, active_levels=0, ancestors=None, selected_pk=0, soft_roots=True, request=None, no_extended=False, to_levels=100):
    """
recursive function for marking all children and handling the active and inactive trees with the level limits
"""
    if not hasattr(target, "childrens"):
        target.childrens = []
    if ancestors == None:
        ancestors = []
    if target.pk in ancestors:
        target.ancestor = True
    if target.pk == selected_pk:
        levels = active_levels
    if (levels <= 0 or (target.soft_root and soft_roots)) and not target.pk in ancestors:
        return
    mark_sibling = False
    for page in pages:
        if page.parent_id and page.parent_id == target.pk:
            if hasattr(target, "selected") or hasattr(target, "descendant"):
                page.descendant = True
            if len(target.childrens):
                target.childrens[-1].last = False
            page.ancestors_ascending = [target] + list(target.ancestors_ascending)
            page.home_pk_cache = target.home_pk_cache
            page.last = True
            target.childrens.append(page)
            find_children(page,
                          pages,
                          levels-1,
                          active_levels,
                          ancestors,
                          selected_pk,
                          soft_roots,
                          request,
                          no_extended,
                          to_levels)
            if hasattr(page, "selected"):
                mark_sibling = True
    if target.navigation_extenders and (levels > 0 or target.pk in ancestors) and not no_extended and target.level < to_levels:
        target.childrens += get_extended_navigation_nodes(
          request,
          levels,
          list(target.ancestors_ascending) + [target],
          target.level,
          to_levels,
          active_levels,
          mark_sibling,
          target.navigation_extenders
        )

def cut_levels(nodes, level):
    """
For cutting the nav_extender levels if you have a from_level in the navigation.
"""
    result = []
    if nodes:
        if nodes[0].level == level:
            return nodes
    for node in nodes:
        result += cut_levels(node.children, level)
    return result

def find_selected(nodes):
    """
Finds a selected nav_extender node
"""
    for node in nodes:
        if hasattr(node, "selected"):
            return node
        if hasattr(node, "ancestor"):
            result = find_selected(node.children)
            if result:
                return result
            
            
def set_language_changer(request, func):
    """
Sets a language chooser function that accepts one parameter: language
The function should return a url in the supplied language
normally you would want to give it the get_absolute_url function with an optional language parameter
example:
def get_absolute_url(self, language=None):
reverse('product_view', args=[self.get_slug(language=language)])
Use this function in your nav extender views that have i18n slugs.
"""
    request._language_changer = func

def language_changer_decorator(language_changer):
    """
A decorator wrapper for set_language_changer.
from menus.utils import language_changer_decorator
@language_changer_decorator(function_get_language_changer_url)
def my_view_function(request, somearg):
pass
"""
    def _decorator(func):
        def _wrapped(request, *args, **kwargs):
            set_language_changer(request, language_changer)
            return func(request, *args, **kwargs)
        _wrapped.__name__ = func.__name__
        _wrapped.__doc__ = func.__doc__
        return _wrapped
    return _decorator

class _SimpleLanguageChanger(object):
    def __init__(self, request):
        self.request = request
        self._app_path = None
        
    @property
    def app_path(self):
        if self._app_path is None:
            page_path = self.get_page_path(self.request.LANGUAGE_CODE)
            if page_path:
                self._app_path = self.request.path[len(page_path):]
            else:
                self._app_path = self.request.path
        return self._app_path
        
    def __call__(self, lang):
        return '%s%s' % (self.get_page_path(lang), self.app_path)
    
    def get_page_path(self, lang):
        if getattr(self.request, 'current_page'):
            try:
                return self.request.current_page.get_absolute_url(language=lang, fallback=False)
            except Title.DoesNotExist:
                return self.request.current_page.get_absolute_url(language=lang, fallback=True)
            return self.request.current_page.get_absolute_url(language=lang)
        else:
            return ''

def simple_language_changer(func):
    def _wrapped(request, *args, **kwargs):
        set_language_changer(request, _SimpleLanguageChanger(request))
        return func(request, *args, **kwargs)
    _wrapped.__name__ = func.__name__
    _wrapped.__doc__ = func.__doc__
    return _wrapped

    

def handle_navigation_manipulators(navigation_tree, request):
    for handler_function_name, name in settings.CMS_NAVIGATION_MODIFIERS:
        func_name = handler_function_name.split(".")[-1]
        modifier = __import__(".".join(handler_function_name.split(".")[:-1]),(),(),(func_name,))
        handler_func = getattr(modifier, func_name)
        handler_func(navigation_tree, request)
    return navigation_tree
Something went wrong with that request. Please try again.