10 $Gruta::VERSION
= '2.1.0-dev';
12 sub sources
{ return @
{$_[0]->{sources
}}; }
13 sub template
{ return $_[0]->{template
}; }
14 sub cgi
{ return $_[0]->{cgi
}; }
16 sub version
{ return $Gruta::VERSION
; }
22 print STDERR
$self->{id
}, ' ', scalar(localtime), ': ', $msg, "\n";
33 if (!exists($self->{calls
}->{$method})) {
35 # cache all calls in the sources
38 foreach my $s ($self->sources()) {
39 if (my $m = $s->can($method)) {
40 push(@c, sub { return $m->($s, @_) });
44 $self->{calls
}->{$method} = [ @c ];
47 foreach my $m (@
{ $self->{calls
}->{$method}}) {
57 return wantarray ?
@r : $r[0];
60 sub topic
{ my $self = shift; return $self->_call('topic', 1, @_); }
61 sub topics
{ my $self = shift; return $self->_call('topics', 0); }
63 sub user
{ my $self = shift; return $self->_call('user', 1, @_); }
64 sub users
{ my $self = shift; return $self->_call('users', 0); }
71 if (! $topic_id || ! $id) {
76 my $ck = $topic_id . '/' . $id;
78 if ($story = $self->{story_cache
}->{$ck}) {
82 if (not $story = $self->_call('story', 1, $topic_id, $id)) {
86 my $format = $story->get('format') || 'grutatxt';
88 if (my $rndr = $self->{renderers_h
}->{$format}) {
92 return $self->{story_cache
}->{$ck} = $story;
96 sub stories
{ my $self = shift; return $self->_call('stories', 0, @_); }
103 my @r = sort { $b->[2] cmp $a->[2] } $self->_call('stories_by_date', 0, $topics, %opts);
105 if ($opts{num
} && scalar(@r) > $opts{num
}) {
106 @r = @r[0 .. $opts{num
} - 1];
114 my $topic_id = shift;
116 my @l = $self->_call('search_stories', 1, $topic_id, @_);
118 return sort { $self->story($topic_id, $a)->get('title') cmp
119 $self->story($topic_id, $b)->get('title') } @l;
122 sub stories_top_ten
{
125 my @l = $self->_call('stories_top_ten', 0, @_);
127 return sort { $b->[0] <=> $a->[0] } @l;
133 my @l = $self->_call('stories_by_tag', 0, @_);
135 return sort { $self->story($a->[0], $a->[1])->get('title') cmp
136 $self->story($b->[0], $b->[1])->get('title') } @l;
142 my @l = $self->_call('tags', 0, @_);
144 return sort { $a->[0] cmp $b->[0] } @l;
147 sub insert_topic
{ my $self = shift; return $self->_call('insert_topic', 1, @_); }
148 sub insert_user
{ my $self = shift; return $self->_call('insert_user', 1, @_); }
149 sub insert_story
{ my $self = shift; return $self->_call('insert_story', 1, @_); }
155 if (@_) { $self->{auth
} = shift; } # Gruta::Data::User
157 return $self->{auth
};
168 $self->_call('purge_old_sessions', 0);
170 if (my $session = $self->_call('session', 1, $sid)) {
171 $u = $session->source->user( $session->get('user_id') );
174 $u->set('sid', $sid);
191 if (my $u = $self->user( $user_id )) {
193 # account expired? go!
194 if (my $xdate = $u->get('xdate')) {
195 if (Gruta
::Data
::today
() > $xdate) {
200 my $p = $u->get('password');
202 if (Gruta
::Data
::crypt($passwd, $p) eq $p) {
204 my $session = Gruta
::Data
::Session
->new(user_id
=> $user_id);
206 $u->source->insert_session( $session );
208 $sid = $session->get('id');
209 $u->set('sid', $sid);
221 if (my $auth = $self->auth()) {
222 if( my $sid = $auth->get('sid')) {
223 if (my $session = $auth->source->session( $sid )) {
224 $session->delete() if $session->can('delete');
229 $self->auth( undef );
234 sub base_url
{ $_[0]->{args
}->{base_url
} || '' };
238 my $st = shift || '';
241 my $ret = $self->base_url();
243 # strip all undefined or empty arguments
244 %args = map { $_, $args{$_} } grep { $args{$_} } keys(%args);
246 if ($self->{args
}->{static_urls
}) {
247 my $kn = scalar(keys(%args));
249 if ($st eq 'INDEX' && $kn == 0) {
252 elsif ($st eq 'TOPIC' && $kn == 1) {
253 return $ret . $args{topic
} . '/';
255 elsif ($st eq 'STORY' && $kn == 2) {
256 return $ret . $args{topic
} . '/' . $args{id
} . '.html';
263 $ret .= '?' . join(';', map { "$_=$args{$_}" } sort keys(%args));
270 sub _topic_special_uri
{
272 my $topic_id = shift;
276 if (my $t = $self->topic($topic_id)) {
277 $ret = sprintf('<a href="%s">%s</a>',
278 $self->url('TOPIC', 'topic' => $topic_id),
283 $ret = "Bad topic $topic_id";
290 sub _story_special_uri
{
292 my $topic_id = shift;
293 my $story_id = shift;
297 if (my $s = $self->story($topic_id, $story_id)) {
298 $ret = sprintf('<a href="%s">%s</a>',
300 'topic' => $topic_id,
307 $ret = "Bad story '$topic_id/$story_id'";
314 sub _img_special_uri
{
319 my $r = sprintf('<img src = "%simg/%s" />',
320 $self->base_url(), $src
324 $r = "<span class = '$class'>" . $r . '</span>';
331 sub _content_special_uri
{
333 my $topic_id = shift;
334 my $story_id = shift;
339 if (my $s = $self->story($topic_id, $story_id)) {
340 $ret = $self->special_uris($s->get($field));
343 $ret = "Bad story '$topic_id/$story_id'";
355 $string =~ s!topic://([\w\d_-]+)!$self->_topic_special_uri($1)!ge;
356 $string =~ s!story://([\w\d_-]+)/([\w\d_-]+)!$self->_story_special_uri($1,$2)!ge;
357 $string =~ s!img://([\w\d_\.-]+)/?([\w\d_-]*)!$self->_img_special_uri($1,$2)!ge;
358 $string =~ s!body://([\w\d_-]+)/([\w\d_-]+)!$self->_content_special_uri($1,$2,'body')!ge;
359 $string =~ s!abstract://([\w\d_-]+)/([\w\d_-]+)!$self->_content_special_uri($1,$2,'abstract')!ge;
365 sub transfer_to_source
{
369 foreach my $id ($self->users()) {
370 my $u = $self->user($id);
371 $dst->insert_user($u);
374 foreach my $topic_id (sort $self->topics()) {
375 my $t = $self->topic($topic_id);
380 if ($nti =~ /-arch$/) {
381 # don't insert topic, just rename
385 $dst->insert_topic($t);
388 foreach my $id ($self->stories($topic_id)) {
390 # get story and its tags
391 my $s = $self->story($topic_id, $id);
392 my @tags = $s->tags();
395 $s->set('topic_id', $nti);
397 my $ns = $dst->insert_story($s);
409 sub flush_story_cache
{
412 $self->{story_cache
} = {};
419 my $g = bless( { @_ } , $class);
421 $g->{id
} ||= 'Gruta';
424 $g->{story_cache
} = {};
425 $g->{renderers_h
} = {};
429 if (ref($g->{sources
}) ne 'ARRAY') {
430 $g->{sources
} = [ $g->{sources
} ];
433 foreach my $s (@
{$g->{sources
}}) {
438 if ($g->{renderers
}) {
439 if (ref($g->{renderers
}) ne 'ARRAY') {
440 $g->{renderers
} = [ $g->{renderers
} ];
443 foreach my $r (@
{$g->{renderers
}}) {
444 $g->{renderers_h
}->{$r->{renderer_id
}} = $r;
448 if ($g->{template
}) {
449 $g->template->data($g);