Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 227 lines (205 sloc) 8.784 kb
e5cce60 @chrisglass Encoding changes for the rest of the CMS stuff.
chrisglass authored
1 # -*- coding: utf-8 -*-
6967eea @digi604 apphooks working, nav extenders as well
digi604 authored
2 from cms.apphook_pool import apphook_pool
abece02 @ojii First stab at faking a server/process restart in ApphooksTestCase.test_0...
ojii authored
3 from cms.exceptions import NoHomeFound
8bf3fdc @fivethreeo better test
fivethreeo authored
4 from cms.utils.moderator import get_page_queryset
5
abece02 @ojii First stab at faking a server/process restart in ApphooksTestCase.test_0...
ojii authored
6 from django.conf import settings
7 from django.conf.urls.defaults import patterns
8 from django.contrib.sites.models import Site
9 from django.core.exceptions import ImproperlyConfigured
10 from django.core.urlresolvers import RegexURLResolver, Resolver404, reverse, \
11 RegexURLPattern
12 from django.utils.importlib import import_module
dcca648 @digi604 selective merge of divio master
digi604 authored
13
14 APP_RESOLVERS = []
39cfb3f Adding apphook support and sample application
cip authored
15
b8148b5 @fivethreeo set current page in apphooked urls
fivethreeo authored
16 def clear_app_resolvers():
8bf3fdc @fivethreeo better test
fivethreeo authored
17 global APP_RESOLVERS
b8148b5 @fivethreeo set current page in apphooked urls
fivethreeo authored
18 APP_RESOLVERS = []
19
0881951 Apphook working, sites integration required
cip authored
20 def applications_page_check(request, current_page=None, path=None):
100a920 @digi604 #31 flat urls working with apphook
digi604 authored
21 """Tries to find if given path was resolved over application.
0881951 Apphook working, sites integration required
cip authored
22 Applications have higher priority than other cms pages.
39cfb3f Adding apphook support and sample application
cip authored
23 """
52be9e9 Sites (domains) unified with django sites framework.
pcicman authored
24 if current_page:
25 return current_page
0881951 Apphook working, sites integration required
cip authored
26 if path is None:
cc09547 @chrisglass - Demined (documented) the details view and other dependencies. We now h...
chrisglass authored
27 # We should get in this branch only if an apphook is active on /
28 # This removes the non-CMS part of the URL.
0881951 Apphook working, sites integration required
cip authored
29 path = request.path.replace(reverse('pages-root'), '', 1)
52be9e9 Sites (domains) unified with django sites framework.
pcicman authored
30 # check if application resolver can resolve this
dcca648 @digi604 selective merge of divio master
digi604 authored
31 for resolver in APP_RESOLVERS:
32 try:
1f7f869 @fivethreeo call applications_page_check from middleware
fivethreeo authored
33 page_id = resolver.resolve_page_id(path)
dcca648 @digi604 selective merge of divio master
digi604 authored
34 # yes, it is application page
35 page = get_page_queryset(request).get(id=page_id)
36 # If current page was matched, then we have some override for content
37 # from cms, but keep current page. Otherwise return page to which was application assigned.
38 return page
39 except Resolver404:
cc09547 @chrisglass - Demined (documented) the details view and other dependencies. We now h...
chrisglass authored
40 # Raised if the page is not managed by an apphook
dcca648 @digi604 selective merge of divio master
digi604 authored
41 pass
42 return None
52be9e9 Sites (domains) unified with django sites framework.
pcicman authored
43
6cae5dd @ojii fixed appresolver when trying to resolve for page id
ojii authored
44 class AppRegexURLResolver(RegexURLResolver):
52be9e9 Sites (domains) unified with django sites framework.
pcicman authored
45 page_id = None
dcca648 @digi604 selective merge of divio master
digi604 authored
46 url_patterns = None
39cfb3f Adding apphook support and sample application
cip authored
47
52be9e9 Sites (domains) unified with django sites framework.
pcicman authored
48 def resolve_page_id(self, path):
49 """Resolves requested path similar way how resolve does, but instead
50 of return callback,.. returns page_id to which was application
51 assigned.
52 """
53 tried = []
54 match = self.regex.search(path)
55 if match:
56 new_path = path[match.end():]
dcca648 @digi604 selective merge of divio master
digi604 authored
57 for pattern in self.url_patterns:
52be9e9 Sites (domains) unified with django sites framework.
pcicman authored
58 try:
59 sub_match = pattern.resolve(new_path)
60 except Resolver404, e:
88dc3ed @digi604 resolver fixed for 1.1
digi604 authored
61 if 'tried' in e.args[0]:
62 tried.extend([(pattern.regex.pattern + ' ' + t) for t in e.args[0]['tried']])
63 elif 'path' in e.args[0]:
64 tried.extend([(pattern.regex.pattern + ' ' + t) for t in e.args[0]['path']])
52be9e9 Sites (domains) unified with django sites framework.
pcicman authored
65 else:
66 if sub_match:
6cae5dd @ojii fixed appresolver when trying to resolve for page id
ojii authored
67 return pattern.page_id
52be9e9 Sites (domains) unified with django sites framework.
pcicman authored
68 tried.append(pattern.regex.pattern)
ae2e226 @ojii fixed issue 463
ojii authored
69 raise Resolver404, {'tried': tried, 'path': new_path}
70
39cfb3f Adding apphook support and sample application
cip authored
71
6cae5dd @ojii fixed appresolver when trying to resolve for page id
ojii authored
72 def recurse_patterns(path, pattern_list, page_id):
dcca648 @digi604 selective merge of divio master
digi604 authored
73 """
74 Recurse over a list of to-be-hooked patterns for a given path prefix
75 """
76 newpatterns = []
77 for pattern in pattern_list:
78 app_pat = pattern.regex.pattern
79 if app_pat.startswith('^'):
80 app_pat = app_pat[1:]
81 regex = r'^%s%s' % (path, app_pat)
82 if isinstance(pattern, RegexURLResolver):
83 # this is an 'include', recurse!
84 resolver = RegexURLResolver(regex, 'cms_appresolver',
85 pattern.default_kwargs, pattern.app_name, pattern.namespace)
6cae5dd @ojii fixed appresolver when trying to resolve for page id
ojii authored
86 resolver.page_id = page_id
ae2e226 @ojii fixed issue 463
ojii authored
87 # see lines 243 and 236 of urlresolvers.py to understand the next line
88 resolver._urlconf_module = recurse_patterns(regex, pattern.url_patterns, page_id)
dcca648 @digi604 selective merge of divio master
digi604 authored
89 else:
90 # Re-do the RegexURLPattern with the new regular expression
91 resolver = RegexURLPattern(regex, pattern.callback,
92 pattern.default_args, pattern.name)
6cae5dd @ojii fixed appresolver when trying to resolve for page id
ojii authored
93 resolver.page_id = page_id
dcca648 @digi604 selective merge of divio master
digi604 authored
94 newpatterns.append(resolver)
95 return newpatterns
52be9e9 Sites (domains) unified with django sites framework.
pcicman authored
96
e5cb644 @ojii appresolver now 'flattens' urlpatterns to fix some resolving issues
ojii authored
97 def _flatten_patterns(patterns):
98 flat = []
99 for pattern in patterns:
100 if isinstance(pattern, RegexURLResolver):
101 flat += _flatten_patterns(pattern.url_patterns)
102 else:
103 flat.append(pattern)
104 return flat
105
7dcc7ac @ojii Moved the 'apphook urls -> urlpatterns' resolving to cms.appresolver.get...
ojii authored
106 def get_app_urls(urls):
107 for urlconf in urls:
108 if isinstance(urlconf, basestring):
109 mod = import_module(urlconf)
110 if not hasattr(mod, 'urlpatterns'):
111 raise ImproperlyConfigured(
112 "URLConf `%s` has no urlpatterns attribute" % urlconf)
113 yield getattr(mod, 'urlpatterns')
114 else:
115 yield urlconf
116
117
dcca648 @digi604 selective merge of divio master
digi604 authored
118 def get_patterns_for_title(path, title):
39cfb3f Adding apphook support and sample application
cip authored
119 """
dcca648 @digi604 selective merge of divio master
digi604 authored
120 Resolve the urlconf module for a path+title combination
121 Returns a list of url objects.
122 """
4e63a49 @samluescher Backwards-compatibility fix for new class-based apphooks
samluescher authored
123 app = apphook_pool.get_apphook(title.application_urls)
6967eea @digi604 apphooks working, nav extenders as well
digi604 authored
124 patterns = []
7dcc7ac @ojii Moved the 'apphook urls -> urlpatterns' resolving to cms.appresolver.get...
ojii authored
125 for pattern_list in get_app_urls(app.urls):
6967eea @digi604 apphooks working, nav extenders as well
digi604 authored
126 if not path.endswith('/'):
127 path += '/'
128 page_id = title.page.id
129 patterns += recurse_patterns(path, pattern_list, page_id)
e5cb644 @ojii appresolver now 'flattens' urlpatterns to fix some resolving issues
ojii authored
130 patterns = _flatten_patterns(patterns)
6967eea @digi604 apphooks working, nav extenders as well
digi604 authored
131 return patterns
52be9e9 Sites (domains) unified with django sites framework.
pcicman authored
132
dcca648 @digi604 selective merge of divio master
digi604 authored
133
134 def get_app_patterns():
135 """
136 Get a list of patterns for all hooked apps.
52be9e9 Sites (domains) unified with django sites framework.
pcicman authored
137
dcca648 @digi604 selective merge of divio master
digi604 authored
138 How this works:
39cfb3f Adding apphook support and sample application
cip authored
139
dcca648 @digi604 selective merge of divio master
digi604 authored
140 By looking through all titles with an app hook (application_urls) we find all
141 urlconf modules we have to hook into titles.
39cfb3f Adding apphook support and sample application
cip authored
142
dcca648 @digi604 selective merge of divio master
digi604 authored
143 If we use the ML URL Middleware, we namespace those patterns with the title
144 language.
145
146 All 'normal' patterns from the urlconf get re-written by prefixing them with
147 the title path and then included into the cms url patterns.
39cfb3f Adding apphook support and sample application
cip authored
148 """
dcca648 @digi604 selective merge of divio master
digi604 authored
149 from cms.models import Title
150 from cms.models.pagemodel import Page
30c356d @digi604 fixes #344 Do not crash admin if there is no site for current settings
digi604 authored
151 try:
152 current_site = Site.objects.get_current()
153 except Site.DoesNotExist:
154 current_site = None
dcca648 @digi604 selective merge of divio master
digi604 authored
155 included = []
39cfb3f Adding apphook support and sample application
cip authored
156
dcca648 @digi604 selective merge of divio master
digi604 authored
157 # we don't have a request here so get_page_queryset() can't be used,
158 # so, if CMS_MODERATOR, use, public() queryset, otherwise
159 # use draft(). This can be done, because url patterns are used just
160 # in frontend
161 is_draft = not settings.CMS_MODERATOR
162 try:
163 home = Page.objects.get_home()
164 home_titles = home.title_set.all()
165 except NoHomeFound:
166 home_titles = []
167 home_slugs = {}
168 for title in home_titles:
169 home_slugs[title.language] = title.slug
170 title_qs = Title.objects.filter(page__publisher_is_draft=is_draft, page__site=current_site)
171
172 if 'cms.middleware.multilingual.MultilingualURLMiddleware' in settings.MIDDLEWARE_CLASSES:
173 use_namespaces = True
174 hooked_applications = {}
175 else:
176 use_namespaces = False
177 hooked_applications = []
7762522 @pcicman Fixes: #17 partially
pcicman authored
178
dcca648 @digi604 selective merge of divio master
digi604 authored
179 # Loop over all titles with an application hooked to them
7036e57 @mrj0 exclude blank app hooks for all databases
mrj0 authored
180 for title in title_qs.exclude(application_urls=None).exclude(application_urls='').select_related():
dcca648 @digi604 selective merge of divio master
digi604 authored
181 if settings.CMS_FLAT_URLS:
182 if title.language in home_slugs:
183 path = title.slug.split(home_slugs[title.language] + "/", 1)[-1]
184 else:
185 path = title.slug
186 if use_namespaces:
187 mixid = "%s:%s:%s" % (path + "/", title.application_urls, title.language)
188 else:
189 mixid = "%s:%s" % (path + "/", title.application_urls)
190 else:
191 if title.language in home_slugs:
192 path = title.path.split(home_slugs[title.language] + "/", 1)[-1]
193 else:
194 path = title.path
195 if use_namespaces:
196 mixid = "%s:%s:%s" % (path + "/", title.application_urls, title.language)
197 else:
198 mixid = "%s:%s" % (path + "/", title.application_urls)
199 if mixid in included:
200 # don't add the same thing twice
201 continue
202 if not settings.APPEND_SLASH:
203 path += '/'
204 if use_namespaces:
205 if title.language not in hooked_applications:
206 hooked_applications[title.language] = []
207 hooked_applications[title.language] += get_patterns_for_title(path, title)
208 else:
209 hooked_applications += get_patterns_for_title(path, title)
210 included.append(mixid)
211 # Build the app patterns to be included in the cms urlconfs
212 app_patterns = []
213 if use_namespaces:
214 for ns, currentpatterns in hooked_applications.items():
215 extra_patterns = patterns('', *currentpatterns)
6cae5dd @ojii fixed appresolver when trying to resolve for page id
ojii authored
216 resolver = AppRegexURLResolver(r'', 'app_resolver', namespace=ns)
dcca648 @digi604 selective merge of divio master
digi604 authored
217 resolver.url_patterns = extra_patterns
218 app_patterns.append(resolver)
219 APP_RESOLVERS.append(resolver)
220 else:
221 extra_patterns = patterns('', *hooked_applications)
6cae5dd @ojii fixed appresolver when trying to resolve for page id
ojii authored
222 resolver = AppRegexURLResolver(r'', 'app_resolver')
dcca648 @digi604 selective merge of divio master
digi604 authored
223 resolver.url_patterns = extra_patterns
224 app_patterns.append(resolver)
225 APP_RESOLVERS.append(resolver)
3d102fd @ojii fixed #476 and added test case to prove #470
ojii authored
226 return app_patterns
Something went wrong with that request. Please try again.