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; };
48 $f{date
} = sub { Gruta
::Data
::today
(); };
49 $f{random
} = sub { $_[rand(scalar(@_))]; };
51 foreach my $p (Gruta
::Data
::Topic
->new->afields()) {
52 $f{'topic_' . $p} = sub {
57 $ret = $data->topic($topic)->get($p) || '';
64 foreach my $p (Gruta
::Data
::Story
->new->afields()) {
65 $f{'story_' . $p} = sub {
71 $ret = $data->story($topic_id, $id)->get($p);
78 $f{story_abstract
} = sub {
79 my $story = $data->story($_[0], $_[1]);
81 return $data->special_uris($story->get('abstract'));
84 $f{story_body
} = sub {
89 if (my $topic = $data->topic($topic_id)) {
90 if (my $story = $data->story($topic_id, $id)) {
91 my $date2 = $story->get('date2');
93 # if no user and story is not freed, bounce
94 if (!$data->auth() && $date2 && $date2 > Gruta
::Data
::today
()) {
95 $ret = '{-restricted_access}';
98 # touch the story if user is not
99 # (potentially) involved on it
100 if (! $topic->is_editor($data->auth())) {
104 $ret = $data->special_uris($story->get('body'));
112 $f{story_date
} = sub {
114 my $topic_id = shift;
119 $ret = $data->story($topic_id, $id)->date($format);
125 $f{story_date2
} = sub {
127 my $topic_id = shift;
132 $ret = $data->story($topic_id, $id)->date2($format);
138 foreach my $p (Gruta
::Data
::User
->new->afields()) {
139 $f{'user_' . $p} = sub {
144 $ret = $data->user($id)->get($p);
151 $f{user_xdate
} = sub {
157 $ret = $data->user($id)->xdate($format);
168 $t = $data->template->template($t);
169 $ret = $self->{_artemus
}->armor($t);
175 $f{save_template
} = sub {
176 my $template = shift;
180 $content = $self->{_artemus
}->unarmor($content);
181 $data->template->save_template($template, $content);
183 return $msg || "Template saved.";
186 $f{loop_topics
} = sub {
187 my $template = shift;
190 return join($sep, map {
191 my $t = $data->topic($_);
192 sprintf('{-%s|%s|%s}',
193 $template, $t->get('name'),
199 $f{loop_users
} = sub {
200 return join($_[1], map { "{-$_[0]|$_}" } $data->users());
203 $f{loop_renderers
} = sub {
204 return join($_[1], map { "{-$_[0]|$_}" }
205 sort(keys(%{$data->{renderers_h
}})));
208 $f{loop_templates
} = sub {
209 return join($_[1], map { "{-$_[0]|$_}" }
210 $data->template->templates());
213 $f{loop_upload_dirs
} = sub {
214 return join($_[1], map { "{-$_[0]|$_}" }
215 $data->cgi->upload_dirs());
218 $f{loop_story_tags
} = sub {
219 my $topic_id = shift;
222 return join($_[1], map { "{-$_[0]|$_}" }
223 $data->story($topic_id, $id)->tags());
226 $f{story_loop_by_date
} = sub {
230 my $template = shift;
236 return join($sep, map { "{-$template|$topic|$_}" }
237 $data->stories_by_date(
248 $f{is_logged_in
} = sub {
249 return $data->auth() ?
1 : 0;
253 return $data->auth() && $data->auth->get('is_admin') ?
1 : 0;
256 $f{is_topic_editor
} = sub {
257 if (my $topic = $data->topic($_[0])) {
258 return $topic->is_editor($data->auth()) ?
1 : 0;
266 my $password = shift;
267 my $error_msg = shift;
269 if ($user_id eq '' || $user_id eq 'cgi-userid') {
270 $error_msg = '{-login_box}';
272 elsif (my $sid = $data->login($user_id, $password)) {
273 $data->cgi->cookie("sid=$sid");
274 $data->cgi->redirect('?t=INDEX');
278 return $error_msg || 'Login incorrect.';
283 $data->cgi->redirect('?t=INDEX');
289 my $redir = shift || 'ADMIN';
292 $data->cgi->redirect('?t=' . $redir);
300 return $data->auth() && $data->auth->get('username') || '';
304 return $data->auth() && $data->auth->get('id') || '';
307 $f{search_stories
} = sub {
308 my $topic_id = shift;
311 my $template = shift || '_story_link_as_item_with_edit';
312 my $sep = shift || '';
315 my @l = $data->search_stories($topic_id, $query, $future);
318 $ret = "<p><b>{-topic_name|$topic_id}</b><br>\n";
320 $ret .= join($sep, map { "{-$template|$topic_id|$_}" } @l);
322 $self->{search_count
} += scalar(@l);
328 $f{story_loop_top_ten
} = sub {
330 my $internal = shift; # ignored
331 my $template = shift;
334 return join($sep, map { "{-$template|$_->[1]|$_->[2]}" }
335 $data->stories_top_ten($num)
339 $f{is_visible_story
} = sub {
340 if (my $story = $data->story($_[0], $_[1])) {
341 return $story->is_visible($data->auth()) ?
1 : 0;
347 $f{redir_if_archived
} = sub {
348 my $template = shift;
349 my $topic_id = shift;
352 if ($topic_id =~ /-arch$/) {
356 my $story = $data->story($topic_id, $id);
358 if ($story->get('topic_id') =~ /-arch$/) {
359 $data->cgi->redirect(
360 sprintf('?t=%s;topic=%s;id=%s',
362 $story->get('topic_id'),
371 $f{topic_has_archive
} = sub {
372 return $data->topic($_[0] . '-arch') ?
1 : 0;
375 $f{save_topic
} = sub {
376 my $topic_id = shift || return 'Error 1';
380 if (not $topic = $data->topic($topic_id)) {
381 $topic = Gruta
::Data
::Topic
->new (
385 $topic->set('name', shift);
386 $topic->set('editors', shift);
387 $topic->set('internal', shift eq 'on' ?
1 : 0);
388 $topic->set('max_stories', shift);
391 if ($topic->source()) {
392 $topic = $topic->save();
395 $topic = $data->insert_topic($topic);
398 return $topic ?
'OK' : 'Error 2';
401 $f{save_story
} = sub {
402 my $topic_id = shift || return 'Error 1';
407 if (not $story = $data->story($topic_id, $id)) {
408 $story = Gruta
::Data
::Story
->new (
409 topic_id
=> $topic_id,
415 $content = $self->{_artemus
}->unarmor($content);
417 $story->set('content', $content);
419 # pick date and drop time
424 my $date = Gruta
::Data
::today
();
426 if ($y && $m && $d) {
427 $date = sprintf("%04d%02d%02d000000", $y, $m, $d);
430 $story->set('date', $date);
431 $story->set('format', shift || 'grutatxt');
441 if ($y && $m && $d) {
442 $date = sprintf("%04d%02d%02d000000", $y, $m, $d);
448 $story->set('date2', $date);
450 # drop all cached stories
451 $data->flush_story_cache();
453 if ($story->source()) {
454 $story = $story->save();
457 $story = $data->insert_story($story);
460 if ($tags ne 'cgi-tags') {
461 $story->tags(split(/\s*,\s*/, $tags));
464 return $story ?
$story->get('id') : 'Error 2';
467 $f{save_user
} = sub {
468 shift; # new (ignored)
469 my $id = shift || return 'Error 1';
470 my $username = shift;
472 my $is_admin = shift;
473 my $can_upload = shift;
480 if ($data->auth->get('username') ne $username &&
481 ! $data->auth->get('is_admin')) {
482 $data->cgi->redirect('?t=LOGIN');
489 if (not $user = $data->user($id)) {
490 $user = Gruta
::Data
::User
->new (
498 $user->set('username', $username);
499 $user->set('email', $email);
501 # these params can only be set by an admin
502 if ($data->auth->get('is_admin')) {
504 $user->set('is_admin', $is_admin eq 'on' ?
1 : 0);
505 $user->set('can_upload', $can_upload eq 'on' ?
1 : 0);
507 if ($xy and $xm and $xd) {
509 sprintf('%04d%02d%02d000000',
513 $user->set('xdate', '');
517 if ($pass1 and $pass2) {
518 if ($pass1 ne $pass2) {
519 croak
"Passwords are different";
522 $user->password($pass1);
525 if ($user->source()) {
526 $user = $user->save();
529 $user = $data->insert_user($user);
532 return $user ?
'OK' : 'Error 2';
537 $data->cgi->upload($_[0], $_[1]);
541 $f{delete_story
} = sub {
542 my $topic_id = shift || return 'Error 1';
545 $data->story($topic_id, $id)->delete();
547 # drop all cached stories
548 $data->flush_story_cache();
553 $f{search_stories_by_tag
} = sub {
555 my $template = shift;
559 my @ret = $data->search_stories_by_tag($tag, $future);
560 $self->{search_count
} = scalar(@ret);
562 return join($sep, map { "{-$template|$_->[0]|$_->[1]}" } @ret);
565 $f{search_count
} = sub { $self->{search_count
}; };
567 $f{content_type
} = sub {
568 $data->cgi->http_headers('Content-Type' => $_[0]);
572 $f{loop_tags
} = sub {
573 return join($_[1], map { "{-$_[0]|$_->[0]|$_->[1]}" }
577 $f{topics
} = sub { join(':', $data->topics()); };
578 $f{templates
} = sub { join(':', $data->template->templates()); };
579 $f{users
} = sub { join(':', $data->users()); };
581 $f{renderers
} = sub { join(':', sort(keys(%{$data->{renderers_h
}}))); };
582 $f{upload_dirs
} = sub { join(':', $data->cgi->upload_dirs()); };
583 $f{tags
} = sub { join(':', $data->tags()); };
586 my $ret = $self->{cgi_vars
}->{$_[0]} || $_[1] || '';
588 return $self->{_artemus
}->armor($ret);
591 $f{story_tags
} = sub {
592 my $topic_id = shift;
597 my $story = $data->story($topic_id, $id);
599 $ret = join(':', $story->tags());
606 $self->{unresolved
} = [];
607 $self->{search_count
} = 0;
609 $self->{_artemus
} = Artemus
->new(
610 'include-path' => $self->{path
},
613 'unresolved' => $self->{unresolved
},
614 'abort' => \
$self->{abort
},
617 if ($self->{cgi_vars
}) {
618 foreach my $k (keys(%{ $self->{cgi_vars
} })) {
619 my $c = $self->{_artemus
}->
620 armor
($self->{cgi_vars
}->{$k});
628 return $self->{_artemus
};
636 if (defined($data)) {
637 $self->{data
} = $data;
638 $self->{_artemus
} = undef;
641 return $self->{data
};
649 $self->{cgi_vars
} = shift;
650 $self->{_artemus
} = undef;
653 return $self->{cgi_vars
};
657 sub process
{ $_[0]->_artemus->process('{-' . $_[1] . '}'); }