@@ 0,0 1,183 @@
+from django.apps import apps
+from django.utils.functional import LazyObject
+from django.utils.module_loading import import_string
+from wiki.compat import include, url
+from wiki.core.plugins import registry
+
+
+class WikiSite:
+
+ """
+ Wiki site configurator.
+
+ To customize, you can define your own subclass, either overriding
+ the view providers, or overriding the functions that collect
+ views and set update WikiConfig.default_site to the dotted import path
+ of your customized site.
+ """
+
+ def __init__(self, name='wiki'):
+ from wiki.conf import settings
+ from wiki.views import accounts, article, deleted_list
+
+ self.name = name
+
+ # root view
+ self.root_view = getattr(self, "root_view", article.CreateRootView.as_view())
+ self.root_missing_view = getattr(self, "root_missing_view", article.MissingRootView.as_view())
+
+ # basic views
+ self.article_view = getattr(self, "article_view", article.ArticleView.as_view())
+ self.article_create_view = getattr(self, "article_create_view", article.Create.as_view())
+ self.article_delete_view = getattr(self, "article_delete_view", article.Delete.as_view())
+ self.article_deleted_view = getattr(self, "article_deleted_view", article.Deleted.as_view())
+ self.article_dir_view = getattr(self, "article_dir_view", article.Dir.as_view())
+ self.article_edit_view = getattr(self, "article_edit_view", article.Edit.as_view())
+ self.article_move_view = getattr(self, "article_move_view", article.Move.as_view())
+ self.article_preview_view = getattr(self, "article_preview_view", article.Preview.as_view())
+ self.article_history_view = getattr(self, "article_history_view", article.History.as_view())
+ self.article_settings_view = getattr(self, "article_settings_view", article.Settings.as_view())
+ self.article_source_view = getattr(self, "article_source_view", article.Source.as_view())
+ self.article_plugin_view = getattr(self, "article_plugin_view", article.Plugin.as_view())
+ self.revision_change_view = getattr(self, "revision_change_view", article.ChangeRevisionView.as_view())
+ self.revision_merge_view = getattr(self, "revision_merge_view", article.MergeView.as_view())
+ self.revision_preview_merge_view = getattr(self, "revision_preview_merge_view", article.MergeView.as_view(preview=True))
+
+ self.search_view = import_string(getattr(self, "search_view", settings.SEARCH_VIEW)).as_view()
+ self.article_diff_view = getattr(self, "article_diff_view", article.DiffView.as_view())
+
+ # account views
+ self.signup_view = getattr(self, "signup_view", accounts.Signup.as_view())
+ self.login_view = getattr(self, "login_view", accounts.Login.as_view())
+ self.logout_view = getattr(self, "logout_view", accounts.Logout.as_view())
+ self.profile_update_view = getattr(self, "profile_update_view", accounts.Update.as_view())
+
+ # deleted list view
+ self.deleted_list_view = getattr(self, "deleted_list_view", deleted_list.DeletedListView.as_view())
+
+ def get_urls(self):
+ urlpatterns = self.get_root_urls()
+ urlpatterns += self.get_accounts_urls()
+ urlpatterns += self.get_deleted_list_urls()
+ urlpatterns += self.get_revision_urls()
+ urlpatterns += self.get_article_urls()
+ urlpatterns += self.get_plugin_urls()
+
+ # This ALWAYS has to be the last of all the patterns since
+ # the paths in theory could wrongly match other targets.
+ urlpatterns += self.get_article_path_urls()
+ return urlpatterns
+
+ @property
+ def urls(self):
+ return self.get_urls(), 'wiki', self.name
+
+ def get_root_urls(self):
+ urlpatterns = [
+ url(r'^$', self.article_view, name='root', kwargs={'path': ''}),
+ url(r'^create-root/$', self.root_view, name='root_create'),
+ url(r'^missing-root/$', self.root_missing_view, name='root_missing'),
+ url(r'^_search/$', self.search_view, name='search'),
+ url(r'^_revision/diff/(?P<revision_id>[0-9]+)/$', self.article_diff_view, name='diff'),
+ ]
+ return urlpatterns
+
+ def get_deleted_list_urls(self):
+ urlpatterns = [
+ url('^_admin/$', self.deleted_list_view, name="deleted_list"),
+ ]
+ return urlpatterns
+
+ def get_accounts_urls(self):
+ from wiki.conf import settings
+ if settings.ACCOUNT_HANDLING:
+ urlpatterns = [
+ url(r'^_accounts/sign-up/$', self.signup_view, name='signup'),
+ url(r'^_accounts/logout/$', self.logout_view, name='logout'),
+ url(r'^_accounts/login/$', self.login_view, name='login'),
+ url(r'^_accounts/settings/$', self.profile_update_view, name='profile_update'),
+ ]
+ else:
+ urlpatterns = []
+ return urlpatterns
+
+ def get_revision_urls(self):
+ urlpatterns = [
+ # This one doesn't work because it don't know
+ # where to redirect after...
+ url(r'^change/(?P<revision_id>[0-9]+)/$', self.revision_change_view, name='change_revision'),
+ url(r'^preview/$', self.article_preview_view, name='preview_revision'),
+ url(r'^merge/(?P<revision_id>[0-9]+)/preview/$', self.revision_preview_merge_view, name='merge_revision_preview'),
+ ]
+ return [
+ url(r'^_revision/(?P<article_id>[0-9]+)/', include(urlpatterns)),
+ ]
+
+ def get_article_urls(self):
+ urlpatterns = [
+ # Paths decided by article_ids
+ url(r'^$', self.article_view, name='get'),
+ url(r'^delete/$', self.article_delete_view, name='delete'),
+ url(r'^deleted/$', self.article_deleted_view, name='deleted'),
+ url(r'^edit/$', self.article_edit_view, name='edit'),
+ url(r'^move/$', self.article_move_view, name='move'),
+ url(r'^preview/$', self.article_preview_view, name='preview'),
+ url(r'^history/$', self.article_history_view, name='history'),
+ url(r'^settings/$', self.article_settings_view, name='settings'),
+ url(r'^source/$', self.article_source_view, name='source'),
+ url(r'^revision/change/(?P<revision_id>[0-9]+)/$', self.revision_change_view, name='change_revision'),
+ url(r'^revision/merge/(?P<revision_id>[0-9]+)/$', self.revision_merge_view, name='merge_revision'),
+ url(r'^plugin/(?P<slug>\w+)/$', self.article_plugin_view, name='plugin'),
+ ]
+ return [
+ url(r'^(?P<article_id>[0-9]+)/', include(urlpatterns)),
+ ]
+
+ def get_article_path_urls(self):
+ urlpatterns = [
+ # Paths decided by URLs
+ url(r'^(?P<path>.+/|)_create/$', self.article_create_view, name='create'),
+ url(r'^(?P<path>.+/|)_delete/$', self.article_delete_view, name='delete'),
+ url(r'^(?P<path>.+/|)_deleted/$', self.article_deleted_view, name='deleted'),
+ url(r'^(?P<path>.+/|)_edit/$', self.article_edit_view, name='edit'),
+ url(r'^(?P<path>.+/|)_move/$', self.article_move_view, name='move'),
+ url(r'^(?P<path>.+/|)_preview/$', self.article_preview_view, name='preview'),
+ url(r'^(?P<path>.+/|)_history/$', self.article_history_view, name='history'),
+ url(r'^(?P<path>.+/|)_dir/$', self.article_dir_view, name='dir'),
+ url(r'^(?P<path>.+/|)_search/$', self.search_view, name='search'),
+ url(r'^(?P<path>.+/|)_settings/$', self.article_settings_view, name='settings'),
+ url(r'^(?P<path>.+/|)_source/$', self.article_source_view, name='source'),
+ url(r'^(?P<path>.+/|)_revision/change/(?P<revision_id>[0-9]+)/$', self.revision_change_view, name='change_revision'),
+ url(r'^(?P<path>.+/|)_revision/merge/(?P<revision_id>[0-9]+)/$', self.revision_merge_view, name='merge_revision'),
+ url(r'^(?P<path>.+/|)_plugin/(?P<slug>\w+)/$', self.article_plugin_view, name='plugin'),
+ # This should always go last!
+ url(r'^(?P<path>.+/|)$', self.article_view, name='get'),
+ ]
+ return urlpatterns
+
+ def get_plugin_urls(self):
+ urlpatterns = []
+ for plugin in registry.get_plugins().values():
+ slug = getattr(plugin, 'slug', None)
+ if slug:
+ article_urlpatterns = plugin.urlpatterns.get('article', [])
+ urlpatterns += [
+ url(r'^(?P<article_id>[0-9]+)/plugin/' + slug + '/',
+ include(article_urlpatterns)),
+ url(r'^(?P<path>.+/|)_plugin/' + slug + '/',
+ include(article_urlpatterns)),
+ ]
+ root_urlpatterns = plugin.urlpatterns.get('root', [])
+ urlpatterns += [
+ url(r'^_plugin/' + slug + '/', include(root_urlpatterns)),
+ ]
+ return urlpatterns
+
+
+class DefaultWikiSite(LazyObject):
+ def _setup(self):
+ WikiSiteClass = import_string(apps.get_app_config('wiki').default_site)
+ self._wrapped = WikiSiteClass()
+
+
+site = DefaultWikiSite()
@@ 0,0 1,92 @@
+from importlib import reload
+
+from django.contrib.sites.models import Site
+from django.test.testcases import TestCase
+from wiki import sites, urls
+from wiki.apps import WikiConfig
+from wiki.compat import include, url
+from wiki.models import Article, URLPath
+
+from ..base import wiki_override_settings
+
+
+class WikiCustomSite(sites.WikiSite):
+ def get_article_urls(self):
+ urlpatterns = [
+ url('^some-prefix/(?P<article_id>[0-9]+)/$', self.article_view, name='get'),
+ ]
+ return urlpatterns
+
+ def get_article_path_urls(self):
+ urlpatterns = [
+ url('^some-other-prefix/(?P<path>.+/|)$', self.article_view, name='get'),
+ ]
+ return urlpatterns
+
+
+class WikiCustomConfig(WikiConfig):
+ default_site = "tests.core.test_sites.WikiCustomSite"
+
+
+urlpatterns = [
+ url(r'^notify/', include('django_nyt.urls')),
+ url(r'', include('wiki.urls')),
+]
+
+
+@wiki_override_settings(
+ INSTALLED_APPS=[
+ 'tests.testdata',
+ 'django.contrib.auth.apps.AuthConfig',
+ 'django.contrib.contenttypes.apps.ContentTypesConfig',
+ 'django.contrib.sessions.apps.SessionsConfig',
+ 'django.contrib.admin.apps.AdminConfig',
+ 'django.contrib.humanize.apps.HumanizeConfig',
+ 'django.contrib.sites.apps.SitesConfig',
+ 'django_nyt.apps.DjangoNytConfig',
+ 'mptt',
+ 'sekizai',
+ 'sorl.thumbnail',
+ 'tests.core.test_sites.WikiCustomConfig',
+ 'wiki.plugins.attachments.apps.AttachmentsConfig',
+ 'wiki.plugins.notifications.apps.NotificationsConfig',
+ 'wiki.plugins.images.apps.ImagesConfig',
+ 'wiki.plugins.macros.apps.MacrosConfig',
+ 'wiki.plugins.globalhistory.apps.GlobalHistoryConfig',
+ ],
+ ROOT_URLCONF='tests.core.test_sites',
+)
+class CustomWikiSiteTest(TestCase):
+ def setUp(self):
+ # Reload wiki.urls since it may have already been instantiated by another test app.
+ self._old_site = sites.site
+ sites.site = sites.DefaultWikiSite()
+ reload(urls)
+
+ def tearDown(self):
+ sites.site = self._old_site
+ reload(urls)
+
+ def test_use_custom_wiki_site(self):
+ self.assertEqual(sites.site.__class__.__name__, 'WikiCustomSite')
+
+ def test_get_absolute_url_if_urlpath_set_is_not_exists__no_root_urlconf(self):
+ a = Article.objects.create()
+
+ self.assertEqual(a.get_absolute_url(), '/some-prefix/1/')
+
+ def test_get_absolute_url_if_urlpath_set_is_exists__no_root_urlconf(self):
+ a1 = Article.objects.create()
+ s1 = Site.objects.create(domain="something.com", name="something.com")
+ u1 = URLPath.objects.create(article=a1, site=s1)
+
+ a2 = Article.objects.create()
+ s2 = Site.objects.create(domain="somethingelse.com", name="somethingelse.com")
+ URLPath.objects.create(
+ article=a2,
+ site=s2,
+ parent=u1,
+ slug='test_slug'
+ )
+
+ self.assertEqual(a2.get_absolute_url(), '/some-other-prefix/test_slug/')