1 package Gruta
::Template
::Artemus
;
7 use base
'Gruta::Template::BASE';
16 my $a = bless( {}, $class );
18 $a->{_artemus
} = undef;
19 $a->{path
} = $args{path
};
30 if (not $self->{_artemus
}) {
31 my $data = $self->data();
39 return '?t=' . $t . ';' . join(';', @_);
42 $f{'add'} = sub { $_[0] + $_[1]; };
43 $f{'sub'} = sub { $_[0] - $_[1]; };
44 $f{'gt'} = sub { $_[0] > $_[1]; };
45 $f{'lt'} = sub { $_[0] < $_[1]; };
46 $f{'eq'} = sub { $_[0] eq $_[1] ?
1 : 0; };
50 my $d = shift || Gruta
::Data
::today
();
52 return Gruta
::Data
::format_date
($d, $fmt);
55 $f{random
} = sub { $_[rand(scalar(@_))]; };
57 foreach my $p (Gruta
::Data
::Topic
->new->afields()) {
58 $f{'topic_' . $p} = sub {
63 if (my $topic = $data->topic($topic)) {
64 $ret = $topic->get($p) || '';
72 foreach my $p (Gruta
::Data
::Story
->new->afields()) {
73 $f{'story_' . $p} = sub {
81 if ($story = $data->story($topic_id, $id)) {
82 $ret = $story->get($p);
90 $f{story_abstract
} = sub {
91 my $story = $data->story($_[0], $_[1]);
93 return $data->special_uris($story->get('abstract'));
96 $f{story_body
} = sub {
101 if (my $topic = $data->topic($topic_id)) {
102 if (my $story = $data->story($topic_id, $id)) {
103 my $date2 = $story->get('date2');
105 # if no user and story is not freed, bounce
106 if (!$data->auth() && $date2 && $date2 > Gruta
::Data
::today
()) {
107 $ret = '{-restricted_access}';
110 # touch the story if user is not
111 # (potentially) involved on it
112 if (! $topic->is_editor($data->auth())) {
116 $ret = $data->special_uris($story->get('body'));
121 if (!defined($ret)) {
122 $data->cgi->redirect('?t=404');
129 $f{story_date
} = sub {
131 my $topic_id = shift;
138 if ($story = $data->story($topic_id, $id)) {
139 $ret = $story->date($format);
146 $f{story_date2
} = sub {
148 my $topic_id = shift;
155 if ($story = $data->story($topic_id, $id)) {
156 $ret = $story->date2($format);
163 foreach my $p (Gruta
::Data
::User
->new->afields()) {
164 $f{'user_' . $p} = sub {
169 $ret = $data->user($id)->get($p);
176 $f{user_xdate
} = sub {
182 $ret = $data->user($id)->xdate($format);
193 $t = $data->template->template($t);
194 $ret = $self->{_artemus
}->armor($t);
200 $f{save_template
} = sub {
201 my $template = shift;
205 $content = $self->{_artemus
}->unarmor($content);
206 $data->template->save_template($template, $content);
208 return $msg || "Template saved.";
211 $f{loop_topics
} = sub {
212 my $template = shift;
215 return join($sep, map {
216 my $t = $data->topic($_);
217 sprintf('{-%s|%s|%s}',
218 $template, $t->get('name'),
224 $f{loop_users
} = sub {
225 return join($_[1], map { "{-$_[0]|$_}" } $data->users());
228 $f{loop_renderers
} = sub {
229 return join($_[1], map { "{-$_[0]|$_}" }
230 sort(keys(%{$data->{renderers_h
}})));
233 $f{loop_templates
} = sub {
234 return join($_[1], map { "{-$_[0]|$_}" }
235 $data->template->templates());
238 $f{loop_upload_dirs
} = sub {
239 return join($_[1], map { "{-$_[0]|$_}" }
240 $data->cgi->upload_dirs());
243 $f{loop_story_tags
} = sub {
244 my $topic_id = shift;
250 if ($story = $data->story($topic_id, $id)) {
251 $ret = join($_[1], map { "{-$_[0]|$_}" }
258 $f{story_loop_by_date
} = sub {
262 my $template = shift;
268 return join($sep, map { "{-$template|$topic|$_->[0]}" }
269 $data->stories_by_date(
280 $f{is_logged_in
} = sub {
281 return $data->auth() ?
1 : 0;
285 return $data->auth() && $data->auth->get('is_admin') ?
1 : 0;
288 $f{is_topic_editor
} = sub {
289 if (my $topic = $data->topic($_[0])) {
290 return $topic->is_editor($data->auth()) ?
1 : 0;
298 my $password = shift;
299 my $error_msg = shift;
301 if ($user_id eq '' || $user_id eq 'cgi-userid') {
302 $error_msg = '{-login_box}';
304 elsif (my $sid = $data->login($user_id, $password)) {
305 $data->cgi->cookie("sid=$sid");
306 $data->cgi->redirect('?t=INDEX');
310 return $error_msg || 'Login incorrect.';
315 $data->cgi->redirect('?t=INDEX');
321 my $redir = shift || 'ADMIN';
324 $data->cgi->redirect('?t=' . $redir);
332 return $data->auth() && $data->auth->get('username') || '';
336 return $data->auth() && $data->auth->get('id') || '';
339 $f{search_stories
} = sub {
340 my $topic_id = shift;
343 my $template = shift || '_story_link_as_item_with_edit';
344 my $sep = shift || '';
347 my @l = $data->search_stories($topic_id, $query, $future);
350 $ret = "<p><b>{-topic_name|$topic_id}</b><br>\n";
353 $ret .= join($sep, map { "{-$template|$topic_id|$_}" } @l);
356 $self->{search_count
} += scalar(@l);
362 $f{is_visible_story
} = sub {
363 if (my $story = $data->story($_[0], $_[1])) {
364 return $story->is_visible($data->auth()) ?
1 : 0;
370 $f{redir_if_archived
} = sub {
371 my $template = shift;
372 my $topic_id = shift;
375 if ($topic_id =~ /-arch$/) {
379 my $story = $data->story($topic_id, $id);
381 if ($story && $story->get('topic_id') =~ /-arch$/) {
382 $data->cgi->redirect(
383 sprintf('?t=%s;topic=%s;id=%s',
385 $story->get('topic_id'),
394 $f{topic_has_archive
} = sub {
395 return $data->topic($_[0] . '-arch') ?
1 : 0;
398 $f{save_topic
} = sub {
399 my $topic_id = shift || return 'Error 1';
403 if (not $topic = $data->topic($topic_id)) {
404 $topic = Gruta
::Data
::Topic
->new (
408 $topic->set('name', shift);
409 $topic->set('editors', shift);
410 $topic->set('internal', shift eq 'on' ?
1 : 0);
411 $topic->set('max_stories', shift);
414 if ($topic->source()) {
415 $topic = $topic->save();
418 $topic = $data->insert_topic($topic);
421 return $topic ?
'OK' : 'Error 2';
424 $f{save_story
} = sub {
425 my $topic_id = shift || return 'Error 1';
430 if (not $story = $data->story($topic_id, $id)) {
431 $story = Gruta
::Data
::Story
->new (
432 topic_id
=> $topic_id,
438 $content = $self->{_artemus
}->unarmor($content);
440 $story->set('content', $content);
442 # pick date and drop time
447 my $date = Gruta
::Data
::today
();
449 if ($y && $m && $d) {
450 $date = sprintf("%04d%02d%02d000000", $y, $m, $d);
453 $story->set('date', $date);
454 $story->set('format', shift || 'grutatxt');
464 if ($y && $m && $d) {
465 $date = sprintf("%04d%02d%02d000000", $y, $m, $d);
471 $story->set('date2', $date);
473 # if there is no userid, add one
474 if (!$story->get('userid')) {
475 $story->set('userid', $data->auth->get('id'));
478 # drop all cached stories
479 $data->flush_story_cache();
481 if ($story->source()) {
482 $story = $story->save();
485 $story = $data->insert_story($story);
488 if ($tags ne 'cgi-tags') {
489 $story->tags(split(/\s*,\s*/, $tags));
492 return $story ?
$story->get('id') : 'Error 2';
495 $f{save_user
} = sub {
496 shift; # new (ignored)
497 my $id = shift || return 'Error 1';
498 my $username = shift;
500 my $is_admin = shift;
501 my $can_upload = shift;
508 if ($data->auth->get('username') ne $username &&
509 ! $data->auth->get('is_admin')) {
510 $data->cgi->redirect('?t=LOGIN');
517 if (not $user = $data->user($id)) {
518 $user = Gruta
::Data
::User
->new (
526 $user->set('username', $username);
527 $user->set('email', $email);
529 # these params can only be set by an admin
530 if ($data->auth->get('is_admin')) {
532 $user->set('is_admin', $is_admin eq 'on' ?
1 : 0);
533 $user->set('can_upload', $can_upload eq 'on' ?
1 : 0);
535 if ($xy and $xm and $xd) {
537 sprintf('%04d%02d%02d000000',
541 $user->set('xdate', '');
545 if ($pass1 and $pass2) {
546 if ($pass1 ne $pass2) {
547 croak
"Passwords are different";
550 $user->password($pass1);
553 if ($user->source()) {
554 $user = $user->save();
557 $user = $data->insert_user($user);
560 return $user ?
'OK' : 'Error 2';
565 $data->cgi->upload($_[0], $_[1]);
569 $f{delete_story
} = sub {
570 my $topic_id = shift || return 'Error 1';
573 $data->story($topic_id, $id)->delete();
575 # drop all cached stories
576 $data->flush_story_cache();
581 $f{search_count
} = sub { $self->{search_count
}; };
583 $f{content_type
} = sub {
584 $data->cgi->http_headers('Content-Type' => $_[0]);
588 $f{topics
} = sub { join(':', $data->topics()); };
589 $f{templates
} = sub { join(':', $data->template->templates()); };
590 $f{users
} = sub { join(':', $data->users()); };
592 $f{renderers
} = sub { join(':', sort(keys(%{$data->{renderers_h
}}))); };
593 $f{upload_dirs
} = sub { join(':', $data->cgi->upload_dirs()); };
594 $f{tags
} = sub { join(':', map { $_->[0] . ',' . $_->[1] } $data->tags()); };
597 my $ret = $self->{cgi_vars
}->{$_[0]} || $_[1] || '';
599 return $self->{_artemus
}->armor($ret);
602 $f{story_tags
} = sub {
603 my $topic_id = shift;
608 my $story = $data->story($topic_id, $id);
610 $ret = join(':', $story->tags());
616 $f{stories_by_date
} = sub {
620 my $from_date = shift;
624 my @ret = map { join(',', @
{$_}) }
625 $data->stories_by_date(
627 [ map { (split(',', $_))[0] }
637 $self->{search_count
} += scalar(@ret);
639 return join(':', @ret);
642 $f{stories_by_tag
} = sub {
647 my @ret = $data->stories_by_tag(
649 [ map { (split(',', $_))[0] }
654 $self->{search_count
} += scalar(@ret);
656 return join(':', map { $_->[0] . ',' . $_->[1] } @ret);
659 $f{stories_top_ten
} = sub {
662 return join(':', map { join(',', @
{$_}) }
663 $data->stories_top_ten($num)
668 $self->{unresolved
} = [];
669 $self->{search_count
} = 0;
671 $self->{_artemus
} = Artemus
->new(
672 'include-path' => $self->{path
},
675 'unresolved' => $self->{unresolved
},
676 'abort' => \
$self->{abort
},
679 if ($self->{cgi_vars
}) {
680 foreach my $k (keys(%{ $self->{cgi_vars
} })) {
681 my $c = $self->{_artemus
}->
682 armor
($self->{cgi_vars
}->{$k});
690 return $self->{_artemus
};
698 if (defined($data)) {
699 $self->{data
} = $data;
700 $self->{_artemus
} = undef;
703 return $self->{data
};
711 $self->{cgi_vars
} = shift;
712 $self->{_artemus
} = undef;
715 return $self->{cgi_vars
};
719 sub process
{ $_[0]->_artemus->process('{-' . $_[1] . '}'); }