The template Artemus function now armors its content.
[gruta.git] / Gruta / Template / Artemus.pm
blob2080af5bf78db3407f7adefa0adbf2800fb7a6e4
1 package Gruta::Template::Artemus;
3 use strict;
4 use warnings;
6 use base 'Gruta::Template::BASE';
8 use Artemus;
9 use Gruta::Data;
11 sub new {
12 my $class = shift;
13 my %args = @_;
15 my $a = bless( {}, $class );
17 $a->{_artemus} = undef;
18 $a->{path} = $args{path};
20 return $a;
24 sub _artemus {
25 my $self = shift;
27 if (not $self->{_artemus}) {
28 my $data = $self->data();
30 my %f = ();
31 my %v = ();
33 $f{l} = sub {
34 my $t = shift;
36 return '?t=' . $t . ';' . join(';', @_);
39 $f{'add'} = sub { $_[0] + $_[1]; };
40 $f{'sub'} = sub { $_[0] - $_[1]; };
41 $f{'gt'} = sub { $_[0] > $_[1]; };
42 $f{'lt'} = sub { $_[0] < $_[1]; };
43 $f{'eq'} = sub { $_[0] eq $_[1] ? 1 : 0; };
45 $f{date} = sub { $data->today(); };
46 $f{random} = sub { $_[rand(scalar(@_))]; };
48 foreach my $p (Gruta::Data::Topic->new->afields()) {
49 $f{'topic_' . $p} = sub {
50 return $data->topic($_[0])->get($p);
54 foreach my $p (Gruta::Data::Story->new->afields()) {
55 $f{'story_' . $p} = sub {
56 return $data->story($_[0], $_[1])->get($p);
60 $f{story_body} = sub {
61 my $story = $data->story($_[0], $_[1]);
62 my $ret = $story->get('body');
64 if (not $data->auth()) {
65 $story->touch();
68 return $ret;
71 $f{story_date} = sub {
72 return $data->story($_[1], $_[2])->date($_[0]);
75 foreach my $p (Gruta::Data::User->new->afields()) {
76 $f{'user_' . $p} = sub {
77 return $data->user($_[0])->get($p);
81 $f{template} = sub {
82 my $t = $data->template->template($_[0]);
83 return $self->{_artemus}->armor($t);
86 $f{save_template} = sub {
87 return $data->template->save_template($_[0], $_[1]);
90 $f{loop_topics} = sub {
91 my $template = shift;
92 my $sep = shift;
94 return join($sep, map {
95 my $t = $data->topic($_);
96 sprintf('{-%s|%s|%s}',
97 $template, $t->get('name'),
98 $t->get('id')
100 } $data->topics());
103 $f{loop_users} = sub {
104 return join($_[1], map { "{-$_[0]|$_}" } $data->users());
107 $f{loop_renderers} = sub {
108 return join($_[1], map { "{-$_[0]|$_}" }
109 sort(keys(%{$data->{renderers_h}})));
112 $f{loop_templates} = sub {
113 return join($_[1], map { "{-$_[0]|$_}" }
114 $data->template->templates());
117 $f{story_loop_by_date} = sub {
118 my $topic = shift;
119 my $num = shift;
120 my $offset = shift;
121 my $template = shift;
122 my $sep = shift;
123 my $from = shift;
124 my $to = shift;
125 my $future = shift;
127 return join($sep, map { "{-$template|$topic|$_}" }
128 $data->stories_by_date(
129 $topic,
130 num => $num,
131 offset => $offset,
132 from => $from,
133 to => $to,
134 future => $future
139 $f{is_logged_in} = sub {
140 return $data->auth() ? 1 : 0;
143 $f{is_admin} = sub {
144 if ($data->auth() and $data->auth->get('is_admin')) {
145 return 1;
147 return 0;
150 $f{is_topic_editor} = sub {
151 my $auth;
153 if (not $auth = $data->auth()) {
154 return 0;
157 if ($auth->get('is_admin')) {
158 return 1;
161 my $topic;
163 if (not $topic = $data->topic($_[0])) {
164 return 0;
167 if (my $editors = $topic->get('editors') and
168 my $user_id = $auth->get('id')) {
169 return 1 if $editors =~/\b$user_id\b/;
172 return 0;
175 $f{login} = sub {
176 my $user_id = shift;
177 my $password = shift;
178 my $error_msg = shift;
180 if ($user_id eq '' || $user_id eq 'cgi-userid') {
181 $error_msg = '{-login_box}';
183 elsif (my $sid = $data->login($user_id, $password)) {
184 $data->cgi->cookie("sid=$sid");
185 $data->cgi->redirect('?t=INDEX');
186 $self->{abort} = 1;
189 return $error_msg || 'Login incorrect.';
192 $f{logout} = sub {
193 $data->logout();
194 $data->cgi->redirect('?t=INDEX');
195 $self->{abort} = 1;
198 $f{assert_logged_in} = sub {
199 if (not $data->auth()) {
200 $data->cgi->redirect('?t=LOGIN');
201 $self->{abort} = 1;
204 return '';
207 $f{assert_admin} = sub {
208 if ($data->auth() and $data->auth->get('is_admin')) {
209 return '';
212 $data->cgi->redirect('?t=LOGIN');
213 $self->{abort} = 1;
216 $f{username} = sub {
217 my $ret = '';
219 if ($data->auth()) {
220 $ret = $data->auth->get('username');
223 return $ret;
226 $f{search_stories} = sub {
227 my $topic_id = shift;
228 my $query = shift;
230 return "search_stories: FIXME";
233 $f{story_loop_top_ten} = sub {
234 my $num = shift;
235 my $internal = shift; # ignored
236 my $template = shift;
237 my $sep = shift;
239 return join($sep, map { "{-$template|$_->[1]|$_->[2]}" }
240 $data->stories_top_ten($num)
244 $f{assert_visible_story} = sub {
245 my $story = $data->story($_[0], $_[1]);
246 my $ret = '';
248 if (!$data->auth() && $story->get('date') > $data->today()) {
249 $data->cgi->redirect('?t=404');
250 $self->{abort} = 1;
253 return $ret;
256 $f{redir_if_archived} = sub {
257 my $template = shift;
258 my $topic_id = shift;
259 my $id = shift;
261 if ($topic_id =~ /-arch$/) {
262 return '';
265 my $story = $data->story($topic_id, $id);
267 if ($story->get('topic_id') =~ /-arch$/) {
268 $data->cgi->redirect(
269 sprintf('?t=%s;topic=%s;id=%s',
270 $template,
271 $story->get('topic_id'),
272 $id)
274 $self->{abort} = 1;
277 return '';
280 $f{topic_has_archive} = sub {
281 return $data->topic($_[0] . '-arch') ? 1 : 0;
284 $self->{abort} = 0;
285 $self->{unresolved} = [];
287 $self->{_artemus} = Artemus->new(
288 'include-path' => $self->{path},
289 'funcs' => \%f,
290 'vars' => \%v,
291 'unresolved' => $self->{unresolved},
292 'abort' => \$self->{abort},
295 if ($self->{cgi_vars}) {
296 foreach my $k (keys(%{ $self->{cgi_vars} })) {
297 $v{"cgi-${k}"} =
298 $self->{_artemus}->armor($self->{cgi_vars}->{$k});
303 return $self->{_artemus};
307 sub data {
308 my $self = shift;
309 my $data = shift;
311 if (defined($data)) {
312 $self->{data} = $data;
313 $self->{_artemus} = undef;
316 return $self->{data};
320 sub cgi_vars {
321 my $self = shift;
323 if (@_) {
324 $self->{cgi_vars} = shift;
325 $self->{_artemus} = undef;
328 return $self->{cgi_vars};
332 sub process { $_[0]->_artemus->process('{-' . $_[1] . '}'); }