root/veekun/trunk/lib/Vee/Controller/Forum/Create.pm @ 406

Revision 406, 10.5 KB (checked in by eevee, 22 months ago)

Database refactoring. Renamed columns and tables to be more consistent and more readable. (#58)

Line 
1package Vee::Controller::Forum::Create;
2
3use strict;
4use warnings;
5use base 'Catalyst::Controller';
6use Vee::BBCode;
7use Vee::Utils;
8use Vee::Utils::Forum;
9
10use DateTime;
11
12=head1 NAME
13
14Vee::Controller::Forum::Create - Forum posting Controller
15
16=head1 SYNOPSIS
17
18See L<Vee>
19
20=head1 DESCRIPTION
21
22Catalyst Controller for creating new posts or threads.
23
24=head1 METHODS
25
26=cut
27
28=head2 auto
29
30=cut
31
32sub auto : Private {
33    my ($self, $c) = @_;
34   
35    if (!$c->user) {
36        $c->vee_abort('You must be logged in to post.');
37    } elsif ($c->req->method ne 'POST') {
38        $c->vee_abort('This page should only be called as a <code>POST</code>.');
39    }
40   
41    return 1;
42}
43
44=head2 post
45
46=cut
47
48sub post : Local : Args(0) {
49    my ($self, $c) = @_;
50
51    # TODO: make these redir to an actual post page when one exists
52    $c->vee_abort('Please enter a message.') unless $c->req->params->{content} =~ /\S/;
53    $c->vee_abort('No thread id specified.  This should not happen.  Sorry?') unless $c->req->params->{id};
54
55    my $thread = $c->model('DBIC::Threads')->find( $c->req->params->{id}, { prefetch => 'forum' } )
56        or $c->vee_abort('There is no thread with an id of ', $c->req->params->{id}, '.  It may have been nuked while you were typing your reply.');
57
58    if (!can_post($c, $thread)) {
59        $c->vee_abort('You do not have permission to reply to this thread.');
60    }
61
62    my ($parsed_message, @bbcode_errors) = Vee::BBCode::validate_bbcode( $c->req->params->{content} );
63    if (@bbcode_errors) {
64        $c->vee_abort("Your post contains invalid bbcode.  Please go back and fix it.");
65    }
66    $parsed_message = Vee::Utils::fix_newlines( $parsed_message );
67
68    if ('preview' eq lc $c->req->params->{submit}) {
69        $c->detach('post_preview', [ $thread ]);
70    }
71
72    # check for daabaru-post
73    # TODO: apply this to thread creation too?  not as common..  and merge as well?
74    my $last_post = $c->model('DBIC::Posts')->search({
75        thread_id => $thread->id,
76        time      => { '>=', time - $c->site_opts->{post_automerge_time} },
77    }, {
78        order_by  => 'time DESC',
79    })->single;
80
81    my $post;
82    # only do merging/prevention if the last post is this user's       
83    if ($last_post and $last_post->user_id == $c->user->obj->id and $last_post->flags !~ /deleted/) {
84        if ($last_post->content eq $parsed_message) {
85            $c->vee_abort("You have already posted that message recently.");
86        }
87
88        # TODO: what about formats/options of both posts?  not a problem now, but later..
89                # XXX LATIEDIT: The only flag, afaik, is "deleted", which is considered above. Formats, I have no idea ...
90        $post = $c->model('DBIC')->schema->txn_do( sub {
91            my $edit = $c->model('DBIC::Edits')->create({
92                post_id     => $last_post->id,
93                user_id     => $c->user->obj->id,
94                time        => time,
95                old_content => $last_post->content,
96            });
97            $last_post->content(
98                $last_post->content .
99                "\n[hr][i]Automerged:[/i]\n" .
100                $parsed_message
101            );
102            $last_post->last_edit_id( $edit->id );
103            $last_post->time( time );
104            $last_post->update;
105
106            $thread->last_post_id( $last_post->id );
107            $thread->last_post_time( time );
108            $thread->update;
109
110            return $last_post;
111        } );
112    } else {
113        # create the post
114        $post = $c->model('DBIC')->schema->txn_do( sub {
115            my $post = $c->model('DBIC::Posts')->create({
116                thread_id => $thread->id,
117                user_id   => $c->user->obj->id,
118                time      => time,
119                format    => 'bbcode',
120                content   => $parsed_message,
121            });
122            # update thread's last-post stats
123            $thread->last_post_id( $post->id );
124            $thread->last_post_time( time );
125            $thread->post_count( $thread->post_count + 1 );
126            $thread->update;
127            # update forum's last-post stats
128            $thread->forum->last_post_id( $post->id );
129            $thread->forum->post_count( $thread->forum->post_count + 1 );
130            $thread->forum->update;
131            # update user's postcount
132            $c->user->obj->post_count( $c->user->post_count + 1 );
133            $c->user->obj->update;
134            return $post;
135        } );
136    }
137
138    # finito!
139    # Latiedit: this should link to post/ urls.
140    $c->res->redirect( $c->uri('Forum', 'post', $post->id) );
141}
142
143=head2 post_preview
144
145=cut
146
147sub post_preview : Private {
148    my ($self, $c, $thread) = @_;
149    my $s = $c->stash;
150
151    my ($parsed_message, @bbcode_errors) = Vee::BBCode::validate_bbcode( $c->req->params->{content} );
152    if (@bbcode_errors) {
153        $c->vee_abort("Your post contains invalid bbcode.  Please go back and fix it.");
154    }
155    $parsed_message = Vee::Utils::fix_newlines( $parsed_message );
156   
157    my $rows = $c->site_opts->{page_sizes}{posts_preview};
158    my $offset = $c->model('DBIC::Posts')->count({ thread_id => $thread->id }, { order_by => 'me.time ASC' } );
159    $offset = $offset - $rows;
160
161    my $posts_rs = $c->model('DBIC::Posts')->search({ thread_id => $thread->id }, {
162        order_by => 'me.time ASC',
163        offset   => $offset,
164        rows     => $rows
165    } );
166
167    # form generation stuff
168    my $reply_fields = {
169        content => { type => 'textarea', rows => '10', cols => '100' },
170        id => { type => 'hidden' },
171    };
172   
173    my $form = new Vee::Form(
174        id => 'reply',
175        fields => $reply_fields,
176        params => $c->req->params,
177        copy_params => 1,
178    );
179    $form->force( id => $c->req->params->{id} );
180   
181    $s->{template}    = 'forum/thread/preview.tt';
182    $s->{extra_css}   = [qw/forum bbcode/];
183    $s->{posts_rs}    = $posts_rs;
184    $s->{form}        = $form;
185    $s->{tid}         = $c->req->params->{id};
186    $s->{text}        = $parsed_message;
187    $s->{page_title}  = "[PREVIEW] Reply to " . $thread->subject . " - Forums";
188    $s->{page_header} = "Preview Reply to " . $thread->subject;
189    $s->{user}        = $c->user->obj;
190}
191
192=head2 thread
193
194=cut
195
196sub thread : Local : Args(0) {
197    my ($self, $c) = @_;
198   
199    $c->vee_abort('No forum id specified.  This should not happen.  Sorry?') unless $c->req->params->{id};
200
201    my $forum = $c->model('DBIC::Forums')->find( $c->req->params->{id} )
202        or $c->vee_abort('There is no forum with an id of ', $c->req->params->{id}, '.  It may have been deleted while you were typing?');
203
204    if (!can_thread($c, $forum)) {
205        $c->vee_abort('You do not have permission to create threads in this forum.');
206    }
207
208    # TODO: make these redir to an actual post page when one exists
209    $c->vee_abort("You must enter a message.") unless $c->req->params->{content} =~ /\S/;
210    $c->vee_abort("You must enter a subject.") unless $c->req->params->{subject} =~ /\S/;
211   
212    my ($parsed_message, @bbcode_errors) = Vee::BBCode::validate_bbcode( $c->req->params->{content} );
213    if (@bbcode_errors) {
214        $c->detach('thread_preview');
215    } 
216
217    if ('preview' eq lc $c->req->params->{submit}) {
218        $c->detach('thread_preview');
219    }
220   
221    my $subject = $c->req->params->{subject};
222    $subject =~ s/\x0d\x0a|\x0a|\x0d/ /g;
223    $subject = Vee::Utils::cleanse($subject);
224    my $blurb = $c->req->params->{blurb};
225    $blurb =~ s/\x0d\x0a|\x0a|\x0d/ /g;
226    $blurb = Vee::Utils::cleanse($blurb);
227
228    # create the thread
229    my $thread = $c->model('DBIC')->schema->txn_do( sub {
230        my $thread = $c->model('DBIC::Threads')->create({
231            forum_id       => $forum->id,
232            subject        => $subject,
233            first_post_id  => 0,
234            last_post_id   => 0,
235            last_post_time => time,
236            post_count     => 1,
237            blurb          => $blurb,
238        });
239        # create the post
240        my $post = $c->model('DBIC::Posts')->create({
241            thread_id => $thread->id,
242            user_id   => $c->user->obj->id,
243            time      => time,
244            format    => 'bbcode',
245            content   => Vee::Utils::fix_newlines( $parsed_message ),
246        });
247        # update thread's last-post stats
248        $thread->first_post_id( $post->id );
249        $thread->last_post_id( $post->id );
250        $thread->update;
251        # update forum's last-post stats
252        $forum->last_post_id( $post->id );
253        $forum->post_count( $forum->post_count + 1 );
254        $forum->thread_count( $forum->thread_count + 1 );
255        $forum->update;
256        # update user's postcount
257        $c->user->obj->post_count( $c->user->post_count + 1 );
258        $c->user->obj->update;
259        return $thread;
260    } );
261
262    # finito!
263    $c->res->redirect( $c->uri('Forum', 'thread', $thread->id) );
264}
265
266=head2 thread_preview
267
268=cut
269
270sub thread_preview : Private {
271    my ($self, $c) = @_;
272    my $s = $c->stash;
273   
274    # Set up some variables?
275    my $subject = $c->req->params->{subject};
276    my $blurb   = $c->req->params->{blurb};
277    my $content = $c->req->params->{content};
278    my $forum = $c->model('DBIC::Forums')->find( $c->req->params->{id} )
279        or $c->vee_abort('There is no forum with an id of ', $c->req->params->{id}, '.  It may have been deleted while you were typing?');
280   
281    if (!can_thread($c, $forum)) {
282        $c->vee_abort('You do not have permission to create threads in this forum.');
283    }
284   
285    my ($parsed_message, @bbcode_errors) = Vee::BBCode::validate_bbcode($content);
286    if (@bbcode_errors) {
287        $c->vee_abort("Your post contains invalid bbcode.  Please fix it.");
288    }
289   
290    # form generation stuff
291    my $reply_fields = {
292        content => { type => 'textarea', rows => '10', cols => '100' },
293        id => { type => 'hidden' },
294        subject => { type => 'text', maxlength => 48 },
295        blurb => { type => 'text', maxlength => 96 },
296    };
297   
298    my $form = new Vee::Form(
299        id => 'reply',
300        fields => $reply_fields,
301        params => $c->req->params,
302        copy_params => 1,
303    );
304    $form->force( id => $c->req->params->{id} );
305   
306    $s->{extra_css}   = 'forum';
307    $s->{form}        = $form;
308    $s->{fid}         = $c->req->params->{id};
309    $s->{subject}     = $subject;
310    $s->{text}        = $parsed_message;
311    $s->{blurb}       = $blurb;
312    $s->{page_title}  = "[PREVIEW] $subject - Forums";
313    $s->{page_header} = "Preview New Thread";
314    $s->{template}    = 'forum/preview.tt';
315    $s->{user}        = $c->user->obj;
316}
317
318=head1 AUTHOR
319
320Maintainer: Alex "Eevee" Munroe (C<veekun@veekun.com>)
321
322See the included F<AUTHORS> file for a full list of contributers.
323
324=head1 LICENSE
325
326See the included F<LICENSE> file.
327
328=cut
329
3301;
Note: See TracBrowser for help on using the browser.