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 $data->url($t, @_);
45 my $ret = $data->url($t, @_);
47 if ($ret !~ /^http:/) {
48 $ret = "http://{-cfg_host_name}/$ret";
56 my $d = shift || Gruta
::Data
::today
();
58 return Gruta
::Data
::format_date
($d, $fmt);
61 foreach my $p (Gruta
::Data
::Topic
->new->afields()) {
62 $f{'topic_' . $p} = sub {
67 if (my $topic = $data->source->topic($topic)) {
68 $ret = $topic->get($p) || '';
76 foreach my $p (Gruta
::Data
::Story
->new->afields()) {
77 $f{'story_' . $p} = sub {
85 if ($story = $data->source->story($topic_id, $id)) {
86 $ret = $story->get($p);
90 return $self->{_artemus
}->armor($ret);
94 $f{story_abstract
} = sub {
95 my $story = $data->source->story($_[0], $_[1]);
96 my $ret = $data->special_uris($story->get('abstract'));
98 return $self->{_artemus
}->armor($ret);
101 $f{story_body
} = sub {
102 my $topic_id = shift;
106 if (my $topic = $data->source->topic($topic_id)) {
107 if (my $story = $data->source->story($topic_id, $id)) {
108 my $date2 = $story->get('date2');
110 # if no user and story is not freed, bounce
111 if (!$data->auth() && $date2 && $date2 > Gruta
::Data
::today
()) {
112 # return directly to avoid armoring
113 return '{-restricted_access}';
116 # touch the story if user is not
117 # (potentially) involved on it
118 if (! $topic->is_editor($data->auth())) {
122 $ret = $data->special_uris($story->get('body'));
127 if (!defined($ret)) {
128 $data->cgi->redirect('404');
132 return $self->{_artemus
}->armor($ret);
135 $f{story_date
} = sub {
137 my $topic_id = shift;
144 if ($story = $data->source->story($topic_id, $id)) {
145 $ret = $story->date($format);
149 return $self->{_artemus
}->armor($ret);
152 $f{story_date2
} = sub {
154 my $topic_id = shift;
161 if ($story = $data->source->story($topic_id, $id)) {
162 $ret = $story->date2($format);
166 return $self->{_artemus
}->armor($ret);
169 foreach my $p (Gruta
::Data
::User
->new->afields()) {
170 $f{'user_' . $p} = sub {
175 $ret = $data->source->user($id)->get($p);
178 return $self->{_artemus
}->armor($ret);
182 $f{user_xdate
} = sub {
188 $ret = $data->source->user($id)->xdate($format);
199 $t = $data->template->template($t);
200 $ret = $self->{_artemus
}->armor($t);
206 $f{save_template
} = sub {
207 my $template = shift;
211 $content = $self->{_artemus
}->unarmor($content);
212 $data->template->save_template($template, $content);
217 $f{is_logged_in
} = sub {
218 return $data->auth() ?
1 : 0;
222 return $data->auth() && $data->auth->get('is_admin') ?
1 : 0;
225 $f{is_topic_editor
} = sub {
226 if (my $topic = $data->source->topic($_[0])) {
227 return $topic->is_editor($data->auth()) ?
1 : 0;
235 my $password = shift;
236 my $error_msg = shift;
238 if ($user_id eq '') {
239 $error_msg = '{-block_login}';
241 elsif (my $sid = $data->login($user_id, $password)) {
242 $data->cgi->cookie("sid=$sid");
243 $data->cgi->redirect('INDEX');
247 return $error_msg || 'Login incorrect.';
252 $data->cgi->redirect('INDEX');
258 my $redir = shift || 'ADMIN';
261 $data->cgi->redirect($redir);
269 return $data->auth() && $data->auth->get('username') || '';
273 return $data->auth() && $data->auth->get('id') || '';
276 $f{search_stories
} = sub {
277 my $topic_id = shift;
280 my $template = shift || 'link_to_story_with_edit';
281 my $sep = shift || '';
284 my @l = $data->source->search_stories($topic_id, $query, $future);
287 $ret = "<p><b>{-topic_name|$topic_id}</b><br>\n";
290 $ret .= join($sep, map { "<li>{-$template|$topic_id|$_}</li>" } @l);
293 $self->{search_count
} += scalar(@l);
299 $f{is_visible_story
} = sub {
300 if (my $story = $data->source->story($_[0], $_[1])) {
301 return $story->is_visible($data->auth()) ?
1 : 0;
307 $f{redir_if_archived
} = sub {
308 my $template = shift;
309 my $topic_id = shift;
312 if ($topic_id =~ /-arch$/) {
316 my $story = $data->source->story($topic_id, $id);
318 if ($story && $story->get('topic_id') =~ /-arch$/) {
319 $data->cgi->redirect(
321 'topic' => $story->get('topic_id'),
330 $f{topic_has_archive
} = sub {
331 return $data->source->topic($_[0] . '-arch') ?
1 : 0;
334 $f{save_topic
} = sub {
335 my $topic_id = shift || return 'Error 1';
339 if (not $topic = $data->source->topic($topic_id)) {
340 $topic = Gruta
::Data
::Topic
->new (
344 $topic->set('name', shift);
345 $topic->set('editors', shift);
346 $topic->set('internal', shift eq 'on' ?
1 : 0);
347 $topic->set('max_stories', shift);
348 $topic->set('description', shift);
351 if ($topic->source()) {
352 $topic = $topic->save();
355 $topic = $data->source->insert_topic($topic);
358 return $topic ?
'OK' : 'Error 2';
361 $f{save_story
} = sub {
362 my $topic_id = shift || return 'Error 1';
367 if ($id eq '[]' || !$id) {
368 $story = Gruta
::Data
::Story
->new (
369 topic_id
=> $topic_id,
374 $story = $data->source->story($topic_id, $id);
378 $content = $self->{_artemus
}->unarmor($content);
381 $story->set('content', $content);
383 # pick date and drop time
388 my $date = Gruta
::Data
::today
();
390 if ($y && $m && $d) {
391 $date = sprintf("%04d%02d%02d000000", $y, $m, $d);
394 $story->set('date', $date);
395 $story->set('format', shift || 'grutatxt');
405 if ($y && $m && $d) {
406 $date = sprintf("%04d%02d%02d000000", $y, $m, $d);
412 $story->set('date2', $date);
414 $story->set('description', shift);
416 # if there is no userid, add one
417 if (!$story->get('userid')) {
418 $story->set('userid', $data->auth->get('id'));
422 $data->render($story);
424 if ($story->source()) {
425 $story = $story->save();
428 $story = $data->source->insert_story($story);
431 $story->tags(split(/\s*,\s*/, $tags));
433 return $story ?
$story->get('id') : 'Error 2';
436 $f{save_user
} = sub {
437 shift; # new (ignored)
438 my $id = shift || return 'Error 1';
439 my $username = shift;
441 my $is_admin = shift;
442 my $can_upload = shift;
449 if ($data->auth->get('username') ne $username &&
450 ! $data->auth->get('is_admin')) {
451 $data->cgi->redirect('LOGIN');
458 if (not $user = $data->source->user($id)) {
459 $user = Gruta
::Data
::User
->new (
467 $user->set('username', $username);
468 $user->set('email', $email);
470 # these params can only be set by an admin
471 if ($data->auth->get('is_admin')) {
473 $user->set('is_admin', $is_admin eq 'on' ?
1 : 0);
474 $user->set('can_upload', $can_upload eq 'on' ?
1 : 0);
476 if ($xy and $xm and $xd) {
478 sprintf('%04d%02d%02d000000',
482 $user->set('xdate', '');
486 if ($pass1 and $pass2) {
487 if ($pass1 ne $pass2) {
488 croak
"Passwords are different";
491 $user->password($pass1);
494 if ($user->source()) {
495 $user = $user->save();
498 $user = $data->source->insert_user($user);
501 return $user ?
'OK' : 'Error 2';
506 $data->cgi->upload($_[0], $_[1]);
510 $f{delete_story
} = sub {
511 my $topic_id = shift || return 'Error 1';
514 $data->source->story($topic_id, $id)->delete();
519 $f{search_count
} = sub { $self->{search_count
}; };
521 $f{content_type
} = sub {
522 $data->cgi->http_headers('Content-Type' => $_[0]);
526 $f{topics
} = sub { join(':', $data->source->topics()); };
527 $f{templates
} = sub { join(':', $data->template->templates()); };
528 $f{users
} = sub { join(':', $data->source->users()); };
530 $f{renderers
} = sub { join(':', sort(keys(%{$data->{renderers_h
}}))); };
531 $f{upload_dirs
} = sub { join(':', $data->cgi->upload_dirs()); };
532 $f{tags
} = sub { join(':',
533 map { $_->[0] . ',' . $_->[1] } $data->source->tags()); };
536 my $ret = $self->{cgi_vars
}->{$_[0]} || $_[1] || '';
538 return $self->{_artemus
}->armor($ret);
541 $f{story_tags
} = sub {
542 my $topic_id = shift;
547 if (my $story = $data->source->story($topic_id, $id)) {
548 $ret = join(':', $story->tags());
555 $f{stories_by_date
} = sub {
559 my $from_date = shift;
563 my @ret = map { join(',', @
{$_}) }
564 $data->source->stories_by_date(
566 [ map { (split(',', $_))[0] }
576 # $self->{search_count} += scalar(@ret);
578 return join(':', @ret);
581 $f{stories_by_tag
} = sub {
586 my @ret = $data->source->stories_by_tag(
588 [ map { (split(',', $_))[0] }
593 $self->{search_count
} += scalar(@ret);
595 return join(':', map { join(',', @
{$_}) } @ret);
598 $f{stories_top_ten
} = sub {
601 return join(':', map { join(',', @
{$_}) }
602 $data->source->stories_top_ten($num)
607 return 'Gruta ' . $data->version();
611 $self->{unresolved
} = [];
612 $self->{search_count
} = 0;
614 $self->{_artemus
} = Artemus
->new(
615 'include-path' => $self->{path
},
618 'unresolved' => $self->{unresolved
},
619 'abort' => \
$self->{abort
},
623 return $self->{_artemus
};
631 if (defined($data)) {
632 $self->{data
} = $data;
633 $self->{_artemus
} = undef;
636 return $self->{data
};
644 $self->{cgi_vars
} = shift;
645 $self->{_artemus
} = undef;
648 return $self->{cgi_vars
};
656 my $ret = $self->_artemus->process('{-' . $st . '}');
658 # process special HTML variables
661 if ($t = $self->{_artemus
}->{vars
}->{html_title
}) {
662 $ret =~ s!</head>!<title>$t</title></head>!i;
665 if ($t = $self->{_artemus
}->{vars
}->{html_description
}) {
666 $ret =~ s!</head>!<meta name="description" content="$t"></head>!i;
669 if ($t = $self->{_artemus
}->{vars
}->{html_keywords
}) {
670 $ret =~ s!</head>!<meta name="keywords" content="$t"></head>!i;