Crash fix: /forums/999999 would crash instead of 404.
[zzz-spline-forum.git] / splinext / forum / controllers / forum.py
index bf66618..2e94f6a 100644 (file)
@@ -4,33 +4,135 @@ from pylons import config, request, response, session, tmpl_context as c, url
 from pylons.controllers.util import abort, redirect_to
 from routes import request_config
 from sqlalchemy.orm.exc import NoResultFound
+import wtforms
+from wtforms import fields
 
-from spline import model
 from spline.model import meta
 from spline.lib import helpers as h
 from spline.lib.base import BaseController, render
+from splinext.forum import model as forum_model
 
 log = logging.getLogger(__name__)
 
+
+class WritePostForm(wtforms.Form):
+    content = fields.TextAreaField('Content')
+
+class WriteThreadForm(WritePostForm):
+    subject = fields.TextField('Subject')
+
 class ForumController(BaseController):
 
     def forums(self):
-        c.forums = meta.Session.query(model.Forum).order_by(model.Forum.id.asc())
+        c.forums = meta.Session.query(forum_model.Forum) \
+            .order_by(forum_model.Forum.id.asc())
         return render('/forum/forums.mako')
 
     def threads(self, forum_id):
-        try:
-            c.forum = meta.Session.query(model.Forum).get(forum_id)
-        except NoResultFound:
+        c.forum = meta.Session.query(forum_model.Forum).get(forum_id)
+        if not c.forum:
             abort(404)
 
+        c.write_thread_form = WriteThreadForm()
+
+        c.threads = c.forum.threads
+
         return render('/forum/threads.mako')
 
     def posts(self, forum_id, thread_id):
         try:
-            c.thread = meta.Session.query(model.Thread) \
+            c.thread = meta.Session.query(forum_model.Thread) \
                 .filter_by(id=thread_id, forum_id=forum_id).one()
         except NoResultFound:
             abort(404)
 
-        return render('/forum/threads.mako')
+        c.write_post_form = WritePostForm()
+
+        return render('/forum/posts.mako')
+
+
+    def write_thread(self, forum_id):
+        """Provides a form for posting a new thread."""
+        if not c.user.can('forum:create-thread'):
+            abort(403)
+
+        try:
+            c.forum = meta.Session.query(forum_model.Forum) \
+                .filter_by(id=forum_id).one()
+        except NoResultFound:
+            abort(404)
+
+        c.write_thread_form = WriteThreadForm(request.params)
+
+        if request.method != 'POST' or not c.write_thread_form.validate():
+            # Failure or initial request; show the form
+            return render('/forum/write_thread.mako')
+
+
+        # Otherwise, add the post.
+        c.forum = meta.Session.query(forum_model.Forum) \
+            .with_lockmode('update') \
+            .get(c.forum.id)
+
+        thread = forum_model.Thread(
+            forum_id = c.forum.id,
+            subject = c.write_thread_form.subject.data,
+            post_count = 1,
+        )
+        post = forum_model.Post(
+            position = 1,
+            author_user_id = c.user.id,
+            content = c.write_thread_form.content.data,
+        )
+
+        thread.posts.append(post)
+        c.forum.threads.append(thread)
+
+        meta.Session.commit()
+
+        # Redirect to the new thread
+        h.flash("Contribution to the collective knowledge of the species successfully recorded.")
+        redirect_to(controller='forum', action='posts',
+            forum_id=forum_id, thread_id=thread.id,
+            _code=303)
+
+    def write(self, forum_id, thread_id):
+        """Provides a form for posting to a thread."""
+        if not c.user.can('forum:create-post'):
+            abort(403)
+
+        try:
+            c.thread = meta.Session.query(forum_model.Thread) \
+                .filter_by(id=thread_id, forum_id=forum_id).one()
+        except NoResultFound:
+            abort(404)
+
+        c.write_post_form = WritePostForm(request.params)
+
+        if request.method != 'POST' or not c.write_post_form.validate():
+            # Failure or initial request; show the form
+            return render('/forum/write.mako')
+
+
+        # Otherwise, add the post.
+        c.thread = meta.Session.query(forum_model.Thread) \
+            .with_lockmode('update') \
+            .get(c.thread.id)
+
+        post = forum_model.Post(
+            position = c.thread.post_count + 1,
+            author_user_id = c.user.id,
+            content = c.write_post_form.content.data,
+        )
+
+        c.thread.posts.append(post)
+        c.thread.post_count += 1
+
+        meta.Session.commit()
+
+        # Redirect to the thread
+        # XXX probably to the post instead; anchor?  depends on paging scheme
+        h.flash('Your uniqueness has been added to our own.')
+        redirect_to(controller='forum', action='posts',
+            forum_id=forum_id, thread_id=thread_id,
+            _code=303)