Rafał Pitoń 10 лет назад
Родитель
Сommit
52aa9b4b8a

+ 1 - 0
docs/developers/index.rst

@@ -48,6 +48,7 @@ Following references cover everything you want to know about writing your own ap
    shortcuts
    shortcuts
    template_tags
    template_tags
    thread_store
    thread_store
+   thread_types
    user_sites
    user_sites
    validators
    validators
    validating_registrations
    validating_registrations

+ 6 - 1
docs/developers/settings.rst

@@ -264,7 +264,6 @@ MISAGO_NEW_REGISTRATIONS_VALIDATORS
 List of functions to be called when somebody attempts to register on forums using registration form.
 List of functions to be called when somebody attempts to register on forums using registration form.
 
 
 
 
-
 MISAGO_NOTIFICATIONS_MAX_AGE
 MISAGO_NOTIFICATIONS_MAX_AGE
 ----------------------------
 ----------------------------
 
 
@@ -324,6 +323,12 @@ MISAGO_STOP_FORUM_SPAM_USE
 This settings allows you to decide wheter of not `Stop Forum Spam <http://www.stopforumspam.com/>`_ database should be used to validate IPs and emails during new users registrations.
 This settings allows you to decide wheter of not `Stop Forum Spam <http://www.stopforumspam.com/>`_ database should be used to validate IPs and emails during new users registrations.
 
 
 
 
+MISAGO_THREAD_TYPES
+-------------------
+
+List of clasess defining thread types.
+
+
 password_complexity
 password_complexity
 -------------------
 -------------------
 
 

+ 167 - 0
docs/developers/thread_types.rst

@@ -0,0 +1,167 @@
+============
+Thread Types
+============
+
+
+All user-published content in Misago follows basic hierarchy: Forums have threads which have (optionally) polls and posts that have attachments. In addition forums and threads have labels.
+
+Whenever user creates new discussion on forums, sends private message to other user, or reports offensive post, mechanics behind UI are largery the same and result in thread of certain kind being posted in destined section of site.
+
+This system was designed to be extensible to enable developers using Misago as foundation for their community sites to add new content types such as blogs, articles or galleries.
+
+
+Writing custom thread type
+==========================
+
+Thread type is basically UI for users to interact with and Python code implementing features behind it, plus helper object for enabling your models to point to custom views.
+
+Thread type is decided by value of `special_role` attribute of forum model instance that content (thread, post, attachment, etc. ect.) belongs to. Using this value model is able to call `misago.threads.threadtypes.get()` in order to obtain its helper object, which in turn eables model to build links for its UI.
+
+
+Helper classes
+==============
+
+Paths to helper classess definitions are specified in `MISAGO_THREAD_TYPES` settings. Each helper class is expected to define `type_name` attribute corresponding to forum its forum `special_role` attribute.
+
+.. note::
+   If `special_role` is not defined, Misago falls back to `role` attribute.
+
+Once helper class is defined, it's available as "thread_type" attribute on forum, thread, post, event, poll and attachment models.
+
+Models call their helpers to get url's for handling their type UI:
+
+
+get_forum_name
+--------------
+
+.. function:: get_forum_name(forum)
+
+Used to obtain forum name. Useful when thread type uses single forum with predefined name. Should return string.
+
+
+get_forum_absolute_url
+----------------------
+
+.. function:: get_forum_absolute_url(forum)
+
+Used to obtain forum absolute url.
+
+
+get_new_thread_url
+------------------
+
+.. function:: get_new_thread_url(forum)
+
+Used to obtain "post new thread" url for forum.
+
+
+get_reply_url
+-------------
+
+.. function:: get_reply_url(thread)
+
+Used to obtain "post reply" url for thread.
+
+
+get_edit_post_url
+-----------------
+
+.. function:: get_edit_post_url(post)
+
+Used to obtain edit url for post.
+
+
+get_thread_absolute_url
+-----------------------
+
+.. function:: get_thread_absolute_url(thread)
+
+Used to obtain thread absolute url.
+
+
+get_thread_post_url
+-------------------
+
+.. function:: get_thread_post_url(thread, post_id, page)
+
+Used by "go to post" views to build links pointing user to posts. Should return URL to specified thread page with fragment containing specified post.
+
+
+get_thread_last_reply_url
+-------------------------
+
+.. function:: get_thread_last_reply_url(thread)
+
+Should return url to view redirecting to last post in thread.
+
+
+get_thread_new_reply_url
+------------------------
+
+.. function:: get_thread_new_reply_url(thread)
+
+Should return url to view redirecting to first unread post in thread.
+
+
+get_thread_moderated_url
+------------------------
+
+.. function:: get_thread_moderated_url(thread)
+
+Should return url to view returning list of posts in thread that are pending moderator review.
+
+
+get_thread_reported_url
+-----------------------
+
+.. function:: get_thread_reported_url(thread)
+
+Should return url to view returning list of reported posts in thread.
+
+
+get_post_absolute_url
+---------------------
+
+.. function:: get_post_absolute_url(post)
+
+Used to obtain post absolute url.
+
+
+get_post_approve_url
+--------------------
+
+.. function:: get_post_approve_url(post)
+
+Used to obtain url that moderator should follow to approve post.
+
+
+get_post_unhide_url
+-------------------
+
+.. function:: get_post_unhide_url(post)
+
+Used to obtain url that will make hidden post visible.
+
+
+get_post_hide_url
+-----------------
+
+.. function:: get_post_hide_url(post)
+
+Used to obtain url that will make visible post hidden.
+
+
+get_post_delete_url
+-------------------
+
+.. function:: get_post_delete_url(post)
+
+Used to obtain url that will delete post.
+
+
+get_event_edit_url
+------------------
+
+.. function:: get_event_edit_url(event)
+
+Used to obtain url that will handle API calls for hiding/unhiding and deleting thread events.

+ 1 - 0
docs/index.rst

@@ -37,6 +37,7 @@ Table of Contents
    developers/shortcuts
    developers/shortcuts
    developers/template_tags
    developers/template_tags
    developers/thread_store
    developers/thread_store
+   developers/thread_types
    developers/user_sites
    developers/user_sites
    developers/validators
    developers/validators
    developers/validating_registrations
    developers/validating_registrations

+ 5 - 0
misago/conf/defaults.py

@@ -203,6 +203,11 @@ MISAGO_POSTING_MIDDLEWARES = (
 )
 )
 
 
 MISAGO_THREAD_TYPES = (
 MISAGO_THREAD_TYPES = (
+    # category and redirect types
+    'misago.forums.forumtypes.RootCategory',
+    'misago.forums.forumtypes.Category',
+    'misago.forums.forumtypes.Redirect',
+    # real thread types
     'misago.threads.threadtypes.forumthread.ForumThread',
     'misago.threads.threadtypes.forumthread.ForumThread',
     'misago.threads.threadtypes.privatethread.PrivateThread',
     'misago.threads.threadtypes.privatethread.PrivateThread',
     'misago.threads.threadtypes.report.Report',
     'misago.threads.threadtypes.report.Report',

+ 33 - 0
misago/forums/forumtypes.py

@@ -0,0 +1,33 @@
+from django.core.urlresolvers import reverse
+from django.utils.translation import ugettext_lazy as _
+
+from misago.threads.threadtypes import ThreadTypeBase
+
+
+class RootCategory(ThreadTypeBase):
+    type_name = 'root_category'
+
+    def get_forum_name(self, forum):
+        return _('None (will become top level category)')
+
+
+class Category(ThreadTypeBase):
+    type_name = 'category'
+
+    def get_forum_absolute_url(self, forum):
+        if forum.level == 1:
+            formats = (reverse('misago:index'), forum.slug, forum.id)
+            return '%s#%s-%s' % formats
+        else:
+            return reverse('misago:category', kwargs={
+                'forum_id': forum.id, 'forum_slug': forum.slug
+            })
+
+
+class Redirect(ThreadTypeBase):
+    type_name = 'redirect'
+
+    def get_forum_absolute_url(self, forum):
+        return reverse('misago:redirect', kwargs={
+            'forum_id': forum.id, 'forum_slug': forum.slug
+        })

+ 2 - 6
misago/forums/models.py

@@ -87,14 +87,10 @@ class Forum(MPTTModel):
 
 
     @property
     @property
     def thread_type(self):
     def thread_type(self):
-        if self.special_role == 'root_category' or not self.special_role:
-            type_name = 'forum'
-        else:
-            type_name = self.special_role
-        return threadtypes.get(type_name)
+        return threadtypes.get(self.special_role or self.role)
 
 
     def __unicode__(self):
     def __unicode__(self):
-        return self.thread_type.get_forum_name(self)
+        return unicode(self.thread_type.get_forum_name(self))
 
 
     def lock(self):
     def lock(self):
         return Forum.objects.select_for_update().get(id=self.id)
         return Forum.objects.select_for_update().get(id=self.id)

+ 0 - 11
misago/threads/threadtypes/forumthread.py

@@ -1,5 +1,4 @@
 from django.core.urlresolvers import reverse
 from django.core.urlresolvers import reverse
-from django.utils.translation import ugettext_lazy as _
 
 
 from misago.threads.threadtypes import ThreadTypeBase
 from misago.threads.threadtypes import ThreadTypeBase
 
 
@@ -7,17 +6,7 @@ from misago.threads.threadtypes import ThreadTypeBase
 class ForumThread(ThreadTypeBase):
 class ForumThread(ThreadTypeBase):
     type_name = 'forum'
     type_name = 'forum'
 
 
-    def get_forum_name(self, forum):
-        if forum.special_role == 'root_category':
-            return _('None (will become top level category)')
-        else:
-            return forum.name
-
     def get_forum_absolute_url(self, forum):
     def get_forum_absolute_url(self, forum):
-        if forum.level == 1:
-            formats = (reverse('misago:index'), forum.slug, forum.id)
-            return '%s#%s-%s' % formats
-        else:
             return reverse('misago:%s' % forum.role, kwargs={
             return reverse('misago:%s' % forum.role, kwargs={
                 'forum_id': forum.id, 'forum_slug': forum.slug
                 'forum_id': forum.id, 'forum_slug': forum.slug
             })
             })

+ 3 - 0
misago/threads/views/generic/base.py

@@ -36,6 +36,9 @@ class ForumMixin(object):
             queryset, id=kwargs.get('forum_id'), role='forum')
             queryset, id=kwargs.get('forum_id'), role='forum')
 
 
     def check_forum_permissions(self, request, forum):
     def check_forum_permissions(self, request, forum):
+        if forum.special_role:
+            raise Http404()
+
         add_acl(request.user, forum)
         add_acl(request.user, forum)
         allow_see_forum(request.user, forum)
         allow_see_forum(request.user, forum)
         allow_browse_forum(request.user, forum)
         allow_browse_forum(request.user, forum)