OSDN Git Service

a689187063968d265d9d973b323fafe64c781ece
[newslash/newslash.git] / src / newslash_web / lib / Newslash / Plugin / Stories.pm
1 package Newslash::Plugin::Stories;
2 use Mojo::Base 'Mojolicious::Plugin';
3
4 use DateTime;
5 use DateTime::Format::MySQL;
6 use DateTime::Format::ISO8601;
7
8 has 'last_error';
9 has 'app';
10 has 'c';
11
12 sub register {
13     my ($self, $app, $conf) = @_;
14     $self->app($app);
15     $app->helper(stories => sub { $self->c(shift); state $stories = $self; });
16
17     # default config values
18     my $cnf = $app->config->{Stories} ||= {};
19     $cnf->{title_max_byte} ||= 100;
20     $cnf->{submission_karma_bonus} = 3 if !defined $cnf->{submission_karma_bonus};
21 }
22
23 sub related_stories {
24     my ($self, $stoid) = @_;
25     my $stories = $self->app->model('stories');
26
27     return $stories->get_related_items(stoid => $stoid);
28 }
29
30 sub latest {
31     my ($self, $limit) = @_;
32     my $c = $self->c;
33
34     my $user = $c->stash('user');
35     $limit ||= $c->_get_config("item_per_page", 10);
36     my $show_future = $user->{is_admin} ? 1 : 0;
37     my $show_nonpublic = $user->{is_admin} ? 1 : 0;
38
39     my $stories;
40     if ($user->{is_login}) {
41         $stories = $c->model('stories');
42     }
43     else {
44         # TODO: check expire time
45         $stories = $c->ezcache->model('stories', { expire => 60 });
46     }
47     my $items = $stories->select(hide_future => !$user->{is_admin},
48                                  public_only => !$user->{is_admin},
49                                  limit => $limit + 1,
50                                  order_by => {create_time => 'desc'},
51                                 );
52
53     return $items;
54 }
55
56 sub create {
57     my ($self, @params) = @_;
58     my $params = {@params};
59     my $err = "";
60     my $config = $self->app->config->{Stories} || {};
61     my $stories = $self->model("stories");
62
63     # check parameters
64     # required parameters are: uid, title, introtext
65     my $intro_text = $params->{introtext} || $params->{intro_text};
66     $err = "no_introtext_given" if !$intro_text;
67     $err = "no_title_given" if !$params->{title};
68     $err = "no_uid_given" if !$params->{uid};
69
70     # check title length
71     if (length($params->{title}) > $config->{title_max_byte}) {
72         $err = "title_is_too_long";
73     }
74
75     # check timestamp if exists. use ISO8601 style timestamp like: 2006-08-14T02:34:56-0600
76     if ($params->{time}) {
77         $params->{create_time} = $params->{time};
78         delete $params->{time};
79     }
80     if ($params->{create_time}) {
81         my $rex_timestamp = qr/
82                                   ^(\d+)-(\d+)-(\d+)[^ 0-9]+(\d+):(\d+):(\d+(?:\.\d+)?)   # datetime
83                                   (?:Z|([+-])(\d+):(\d+))?$                          # tz
84                               /xi;
85         if ($params->{create_time} =~ $rex_timestamp) {
86             my $dt = DateTime::Format::ISO8601->parse_datetime($params->{time});
87             $params->{create_time} = DateTime::Format::MySQL->format_datetime($dt);
88         }
89     }
90
91     if ($err) {
92         $self->last_error = $err;
93         return;
94     }
95
96     my $dbh = $stories->start_transaction;
97
98     # allocate sid (insert blank story)
99     my ($sid, $stoid) = $stories->allocate_sid(base_datetime => $params->{create_time});
100     if (!$sid) {
101         $self->last_error = "sid allocation failed";
102         $stories->rollback;
103         return;
104     }
105
106     # insert into story_text
107     my $rs = $stories->text->create(stoid => $stoid,
108                                     title => $params->{title},
109                                     introtext => $intro_text,
110                                     bodytext => $params->{bodytext} || $params->{body_text});
111     if (!$rs) {
112         $self->last_error = "insert text failed";
113         $stories->rollback;
114         return;
115     }
116
117     # insert into story
118     $rs = $self->update(stoid => $stoid, %$params);
119     if (!$rs) {
120         $self->last_error = "insert story failed";
121         $stories->rollback;
122         return;
123     }
124
125     # create discussion
126     my $users = $stories->new_instance_of("Users");
127     my $firehose = $stories->new_instance_of("Firehose");
128     my $submissions = $stories->new_instance_of("Submissions");
129
130     # transfer from journal/firehose discussion
131
132     # create firehose item
133
134     # update submitter info
135     my $submission_id = $params->{submission_id} || $params->{subid};
136     if ($submission_id) {
137         # if the story is derived from submission, do some action
138         # first, update firehose item correspod to submission
139         my $rs = $firehose->update(type => "submission",
140                                    src_id => $submission_id,
141                                    accepted => 'yes',
142                                   );
143
144         # get submitter
145         my $submission = $submissions->select(id => $submission_id);
146         my $submitter_uid = $submission->{uid};
147         if (!$users->is_anonymous_uid($submitter_uid)) {
148             # update submitter's karma
149             my $karma_bonus = $config->{submission_karma_bonus};
150             if ($karma_bonus) {
151                 $users->update_karma(uid => $submitter_uid,
152                                      add => $karma_bonus);
153             };
154             $users->class->clear_rookie(uid => $submitter_uid);
155             $users->class->validate_submitter(uid => $submitter_uid);
156         }
157     }
158
159
160 }
161
162 1;
163
164 =encoding utf8
165
166 =head1 NAME
167
168 Newslash::Plugin::Stories - Newslash stories manipulation plugin
169
170 =head1 SYNOPSIS
171
172   # Mojolicious
173   $app->plugin('Newslash::Plugin::Stories');
174
175 =head1 DESCRIPTION
176
177 L<Newslash::Plugin::Stories> is 'Business Logic' layer of Newslash.
178
179
180 =head1 HELPERS
181
182 L<Mojolicious::Plugin::Stories> implements the following helpers.
183
184 =head2 boxes
185
186   [% helpers.boxes() %]
187
188 Fetch box contents for current user and returns them.
189
190 =head2 format_timestamp
191
192   $c->format_timestamp(user => $user, epoch => $epoch, format => "user")
193   $c->format_timestamp(datetime => $dt, format => "simple")
194
195 Return formated string.
196
197 =head1 METHODS
198
199 =head2 register
200
201   $plugin->register(Mojolicious->new);
202
203 Register helpers in L<Mojolicious> application.
204
205 =head1 SEE ALSO
206
207 L<Mojolicious>, L<Mojolicious::Guides>, L<http://mojolicious.org>.
208
209 =cut