]> git.imager.perl.org - bse.git/blobdiff - site/cgi-bin/modules/Generate/Article.pm
allow use of the new template system from static pages
[bse.git] / site / cgi-bin / modules / Generate / Article.pm
index 77a5adb0829377a005f74673ca6e6a3bd3a031e8..01fa0c98a029a3e73c7bc77c46537a9dbc7a793c 100644 (file)
@@ -3,18 +3,20 @@ use strict;
 use BSE::Template;
 use Constants qw(%LEVEL_DEFAULTS $CGI_URI $ADMIN_URI $IMAGES_URI 
                  $UNLISTED_LEVEL1_IN_CRUMBS);
-use Images;
+use BSE::TB::Images;
 use vars qw(@ISA);
 use Generate;
-use Util qw(generate_button);
+use BSE::Regen qw(generate_button);
 use BSE::Util::Tags qw(tag_article);
-use ArticleFiles;
+use BSE::TB::ArticleFiles;
 @ISA = qw/Generate/;
-use DevHelp::HTML;
+use BSE::Util::HTML;
 use BSE::Arrows;
 use Carp 'confess';
 use BSE::Util::Iterate;
 
+our $VERSION = "1.004";
+
 my $excerptSize = 300;
 
 my %level_names = map { $_, $LEVEL_DEFAULTS{$_}{display} }
@@ -59,7 +61,8 @@ sub generate_low {
   my %acts;
   %acts = $self -> baseActs($articles, \%acts, $article, $embedded);
 
-  my $page = BSE::Template->replace($template, $self->{cfg}, \%acts);
+  my $page = BSE::Template->replace($template, $self->{cfg}, \%acts,
+                                   $self->variables);
 
   %acts = (); # try to destroy any circular refs
 
@@ -67,7 +70,7 @@ sub generate_low {
 }
 
 sub tag_title {
-  my ($article, $images, $args, $acts, $funcname, $templater) = @_;
+  my ($cfg, $article, $images, $args, $acts, $funcname, $templater) = @_;
 
   my $which = $args || 'article';
 
@@ -77,23 +80,28 @@ sub tag_title {
   my $title = $templater->perform($acts, $which, 'title');
   my $imagename = $which eq 'article' ? $article->{titleImage} : 
     $templater->perform($acts, $which, 'titleImage');
-  $imagename and
-    return qq!<img src="/images/titles/$imagename"!
-      .qq! border="0" alt="$title" />! ;
+  my $xhtml = $cfg->entry("basic", "xhtml", 1);
+  if ($imagename) {
+    my $html = qq!<img src="/images/titles/$imagename"!;
+    $html .= ' border="0"' unless $xhtml;
+    $html .= qq! class="bse_image_title" alt="$title" />!;
+  }
   my $im;
   if ($which eq 'article') {
     ($im) = grep lc $_->{name} eq 'bse_title', @$images;
   }
   else {
     my $id = $templater->perform($acts, $which, 'id');
-    require Images;
-    my @images = Images->getBy(articleId=>$id);
+    require BSE::TB::Images;
+    my @images = BSE::TB::Images->getBy(articleId=>$id);
     ($im) = grep lc $_->{name} eq 'bse_title', @$images;
   }
 
   if ($im) {
-    return qq!<img src="/images/$im->{image}" width="$im->{width}"!
-      . qq! height="$im->{height}" alt="$title" />!;
+    my $src = $im->{src} || "/images/$im->{image}";
+    $src = escape_html($src);
+    return qq!<img src="$src" width="$im->{width}"!
+      . qq! height="$im->{height}" alt="$title" class="bse_image_title" />!;
   }
   else {
     return $title;
@@ -179,9 +187,7 @@ sub tag_admin {
   my %acts;
   %acts =
     (
-     BSE::Util::Tags->static(\%acts, $cfg),
-     BSE::Util::Tags->admin(\%acts, $cfg),
-     BSE::Util::Tags->secure($self->{request}),
+     $self->{request}->admin_tags,
      article => [ \&tag_article, $article, $cfg ],
      parent => [ \&tag_article, $parent, $cfg ],
      ifParent => $parent,
@@ -192,18 +198,173 @@ sub tag_admin {
 }
 
 sub tag_thumbimage {
-  my ($self, $rcurrent, $images, $args) = @_;
+  my ($self, $rcurrent, $images, $args, $acts, $funcname, $templater) = @_;
 
-  my ($geometry_id, $id, $field) = split ' ', $args;
+  my ($geometry_id, $id, $field) = 
+    DevHelp::Tags->get_parms($args, $acts, $templater);
 
   return $self->do_thumbimage($geometry_id, $id, $field, $images, $$rcurrent);
 }
 
+sub iter_images {
+  my ($self, $images, $arg) = @_;
+
+  if ($arg eq 'all') {
+    return @$images;
+  }
+  elsif ($arg eq 'named') {
+    return grep $_->{name} ne '', @$images;
+  }
+  elsif ($arg =~ m!^named\s+/([^/]+)/$!) {
+    my $re = $1;
+    return grep $_->{name} =~ /$re/i, @$images;
+  }
+  else {
+    return grep $_->{name} eq '', @$images;
+  }
+}
+
+=item filen name
+
+=item filen name field
+
+=item filen -
+
+=item filen - field
+
+Reference an article attached file by name.
+
+C<filen name> will display a link to the file.
+
+C<<filen name I<field> >> will display the given field from the file
+record.  A I<field> of C<url> will be a URL to the file.
+
+If the file identifier given doesn't exist for the current article the
+empty string is returned, allowing use as ifFilen.
+
+The result is unspecified if the I<field> specified isn't one of the
+image record field names and isn't C<url>.
+
+=cut
+
+sub tag_filen {
+  my ($self, $files, $current, $arg, $acts, $funcname, $templater) = @_;
+
+  my ($name, $field, @rest) = 
+    DevHelp::Tags->get_parms($arg, $acts, $templater);
+
+  length $name
+    or return '* name cannot be an empty string *';
+
+  my $file;
+  if ($name eq '-') {
+    $$current
+      or return "* filen - can only be used inside a files iterator *";
+
+    $file = $$current;
+  }
+  else {
+    ($file) = grep $_->{name} eq $name, @$files
+      or return '';
+  }
+
+  return $self->_format_file($file, $field, "@rest");
+}
+
+=item iterator begin files
+
+=item iterator begin files named /foo/
+
+=item iterator begin files filter: FILE[file_handler] eq 'flv'
+
+=item file field
+
+Iterate over files attached to the current article.
+
+<:file field:> can only access simple attributes.
+
+<:filen - field:> can also access any inline representations.
+
+=cut
+
+sub iter_files {
+  my ($self, $files, $arg, $acts, $funcname, $templater) = @_;
+
+  $arg =~ /\S/
+    or return @$files;
+
+  if ($arg =~ m(^named\s+/([^/]+)/$)) {
+    my $re = $1;
+    return grep $_->{name} =~ /$re/i, @$files;
+  }
+  if ($arg =~ m(^filter: (.*)$)s) {
+    my $expr = $1;
+    $expr =~ s/FILE\[(\w+)\]/\$file->$1/g;
+    my $sub = eval 'sub { my $file = shift; ' . $expr . '; }';
+    $sub
+      or die "* Cannot compile sub from filter $expr: $@ *";
+    return grep $sub->($_), @$files;
+  }
+
+  die "* Unknown type of file filter expression *";
+}
+
+=item iterator: crumbs/crumb
+
+Iterators over the ancestor tree from the article parent to the root.
+
+Parameters include:
+
+=over
+
+=item *
+
+showtop - the top level article is included even if unlisted
+
+=item *
+
+listedonly - only listed articles in the tree are included
+
+=back
+
+The default depends on the value of $Constants::UNLISTED_LEVEL1_IN_CRUMBS.
+
+=cut
+
+sub iter_crumbs {
+  my ($self, $crumbs, $args) = @_;
+
+  $args ||= $UNLISTED_LEVEL1_IN_CRUMBS ? 'showtop' : 'listedonly';
+  if ($args eq 'showtop') {
+    return @$crumbs;
+  }
+  else {
+    return grep $_->{listed}, @$crumbs;
+  }
+}
+
+sub tag_ifUnderThreshold {
+  my ($self, $article, $args) = @_;
+
+  my $count;
+  my $what = $args || '';
+  if ($self->{kids}{$article->{id}}{$what}) {
+    $count = @{$self->{kids}{$article->{id}}{$what}};
+  }
+  else {
+    $count = @{$self->{kids}{$article->{id}}{children}};
+  }
+
+  return $count <= $article->{threshold};
+}
+
 sub baseActs {
   my ($self, $articles, $acts, $article, $embedded) = @_;
 
-  my $cfg = $self->{cfg} || BSE::Cfg->new;
+  my $cfg = $self->{cfg} || BSE::Cfg->single;
 
+  $self->set_variable(article => $article);
+  $self->set_variable(embedded => $embedded);
   # used to generate the list (or not) of children to this article
   my $child_index = -1;
   my @children = $articles->listedChildren($article->{id});
@@ -220,19 +381,20 @@ sub baseActs {
     unshift(@crumbs, $crumb) if $crumb->{listed} == 1 || $crumb->{level} == 1;
     $temp = $crumb;
   }
-  my $crumb_index = -1;
-  my @work_crumbs; # set by the crumbs iterator
+  #my $crumb_index = -1;
+  #my @work_crumbs; # set by the crumbs iterator
+  my $current_crumb;
 
   my $parent = $articles->getByPkey($article->{parentid});
   my $section = @crumbs ? $crumbs[0] : $article;
 
-  my @images = Images->getBy('articleId', $article->{id});
+  my @images = BSE::TB::Images->getBy('articleId', $article->{id});
   my @unnamed_images = grep $_->{name} eq '', @images;
   my @iter_images;
   my $image_index = -1;
   my $had_image_tags = 0;
   my @all_files = sort { $b->{displayOrder} <=> $a->{displayOrder} }
-    ArticleFiles->getBy(articleId=>$article->{id});
+    BSE::TB::ArticleFiles->getBy(articleId=>$article->{id});
   my @files = grep !$_->{hide_from_list}, @all_files;
   
   my $blank = qq!<img src="$IMAGES_URI/trans_pixel.gif"  width="17" height="13" border="0" align="absbottom" alt="" />!;
@@ -251,9 +413,15 @@ sub baseActs {
     @allkids     = $article->all_visible_kids;
     @stepparents  = $article->visible_step_parents;
   }
+  $self->{kids}{$article->{id}}{stepkids} = \@stepkids;
+  $self->{kids}{$article->{id}}{allkids} = \@allkids;
+  $self->{kids}{$article->{id}}{children} = \@children;
+
   my $allkids_index;
   my $current_image;
-  my $art_it = BSE::Util::Iterate::Article->new(cfg =>$cfg);
+  my $current_file;
+  my $art_it = BSE::Util::Iterate::Article->new(cfg =>$cfg, admin => $self->{admin}, top => $self->{top});
+  my $it = BSE::Util::Iterate->new;
   # separate these so the closures can see %acts
   my %acts =
     (
@@ -264,7 +432,7 @@ sub baseActs {
        my $which = shift || 'article';
        return $acts->{$which} && $acts->{$which}->('titleImage')
      },
-     title => [ \&tag_title, $article, \@images ],
+     title => [ \&tag_title, $cfg, $article, \@images ],
      thumbnail =>
      sub {
        my ($args, $acts, $name, $templater) = @_;
@@ -293,27 +461,7 @@ sub baseActs {
         $templater->perform($acts, $which, 'thumbImage');
      },
      ifUnderThreshold => 
-     sub { 
-       if ($article->{threshold} !~ /\d/) {
-        use Data::Dumper;
-        use Carp qw/cluck/;
-        print STDERR Dumper($article);
-        cluck 'Why is a template name in \$article->{threshold}?';
-       }
-
-       my $count;
-       my $what = $_[0] || '';
-       if ($what eq 'stepkids') {
-        $count = @stepkids;
-       }
-       elsif ($what eq 'allkids') {
-        $count = @allkids;
-       }
-       else {
-        $count = @children;
-       }
-       $count <= $article->{threshold};
-     },
+     [ tag_ifUnderThreshold => $self, $article ],
      ifChildren => sub { scalar @children },
      iterate_children_reset => sub { $child_index = -1; },
      iterate_children =>
@@ -351,45 +499,17 @@ sub baseActs {
      },
 
      # used to display a navigation path of parent sections
-     iterate_crumbs_reset => 
-     sub {
-       my $args = $_[0];
-       $args ||= $UNLISTED_LEVEL1_IN_CRUMBS ? 'showtop' : 'listedonly';
-       if ($args eq 'showtop') {
-        @work_crumbs = @crumbs;
-       }
-       else {
-        @work_crumbs = grep $_->{listed}, @crumbs;
-       }
-       $crumb_index = -1;
-     },
-     iterate_crumbs =>
-     sub {
-       return ++$crumb_index < @work_crumbs;
-     },
+     $art_it->make_iterator([ iter_crumbs => $self, \@crumbs ],
+                           'crumb', 'crumbs', undef, undef,
+                           'nocache', \$current_crumb),
      crumbs =>
      sub {
-       # obsolete me
-       return tag_article($work_crumbs[$crumb_index], $cfg, $_[0]);
-     },
-     crumb =>
-     sub {
-       return tag_article($work_crumbs[$crumb_index], $cfg, $_[0]);
+       # this is obsolete
+       $cfg->entry('basic', 'warn_obsolete', 0)
+        and print STDERR "* crumbs tag obsolete *\n";
+       return tag_article($current_crumb, $cfg, $_[0]);
      },
-     ifCrumbs =>
-     sub {
-       my $args = $_[0];
-       $args ||= $UNLISTED_LEVEL1_IN_CRUMBS ? 'showtop' : 'listedonly';
-
-       my @temp;
-       if ($args eq 'showtop') {
-        return scalar @crumbs;
-       }
-       else {
-        return scalar grep $_->{listed}, @crumbs;
-       }
-     },
-
+     
      # access to parent
      ifParent => sub { $parent },
      parent =>
@@ -464,35 +584,8 @@ HTML
      },
      ifStepAncestor => [ \&tag_ifStepAncestor, $article ],
      # access to images, if any
-     iterate_images_reset => 
-     sub { 
-       my ($arg) = @_;
-       $image_index = -1;
-       if ($arg eq 'all') {
-        @iter_images = @images;
-       }
-       elsif ($arg eq 'named') {
-        @iter_images = grep $_->{name} ne '', @images;
-       }
-       elsif ($arg =~ m!^named\s+/([^/]+)/$!) {
-        my $re = $1;
-        @iter_images = grep $_->{name} =~ /$re/i, @images;
-       }
-       else {
-        @iter_images = @unnamed_images;
-       }
-       $current_image = undef;
-     },
-     iterate_images => 
-     sub { 
-       if (++$image_index < @iter_images) {
-        $current_image = $iter_images[$image_index];
-       }
-       else {
-        $current_image = undef;
-       }
-       $current_image;
-     },
+     $it->make_iterator([ iter_images => $self, \@images ], 'image', 'images', \@iter_images, \$image_index, 'nocache', \$current_image),
+     # override the generated image tag
      image =>
      sub {
        my ($which, $align, $rest) = split ' ', $_[0], 3;
@@ -522,34 +615,22 @@ HTML
        $self->_format_image($im, $align, $rest);
      },
      ifImage => sub { $_[0] >= 1 && $_[0] <= @images },
-     ifImages => 
-     sub {
-       my ($arg) = @_;
-       if ($arg eq 'all' or $arg eq '') {
-        return @images;
-       }
-       elsif ($arg eq 'named') {
-        return grep $_->{name} ne '', @images;
-       }
-       elsif ($arg =~ m!^named\s+/([^/]+)/$!) {
-        my $re = $1;
-        return grep $_->{name} =~ /$re/i, @images;
-       }
-       elsif ($arg eq 'unnamed') {
-        return @unnamed_images;
-       }
-       else {
-        return 0;
-       }
-     },
-     image_index => sub { $image_index },
      thumbimage => [ tag_thumbimage => $self, \$current_image, \@images ],
-     BSE::Util::Tags->make_iterator(\@files, 'file', 'files'),
+     $it->make
+     (
+      plural => "files",
+      single => "file",
+      code => [ iter_files => $self, \@files ],
+      nocache => 1,
+      store => \$current_file,
+     ),
+     filen => [ tag_filen => $self, \@files, \$current_file ],
      BSE::Util::Tags->make_iterator(\@stepkids, 'stepkid', 'stepkids'),
      $art_it->make_iterator(undef, 'allkid', 'allkids', \@allkids, \$allkids_index),
      $art_it->make_iterator(undef, 'stepparent', 'stepparents', \@stepparents),
      top => [ \&tag_article, $self->{top} || $article, $cfg ],
      ifDynamic => $dynamic,
+     ifStatic => !$dynamic,
      ifAccessControlled => [ \&tag_ifAccessControlled, $article ],
     );
 
@@ -597,7 +678,7 @@ sub tag_ifDynamic {
 }
 
 sub tag_ifAccessControlled {
-  my ($article, $arg, $acts, $templater) = @_;
+  my ($article, $arg, $acts, $funcname, $templater) = @_;
 
   if ($arg) {
     if ($acts->{$arg}) {
@@ -618,28 +699,54 @@ sub tag_ifAccessControlled {
     $article->is_access_controlled : 0;
 }
 
+sub get_image {
+  my ($self, $image_id, $images) = @_;
+
+  my $im;
+  if ($image_id =~ /^\d+$/) {
+    $image_id >= 1 && $image_id <= @$images
+      or return ( undef, "* Out of range image index '$image_id' *" );
+    
+    $im = $images->[$image_id-1];
+  }
+  elsif ($image_id =~ /^[^\W\d]\w*$/) {
+    ($im) = grep $_->{name} eq $image_id, @$images
+      or return ( undef, "* Unknown image identifier '$image_id' *" );
+  }
+  else {
+    return ( undef, "* Unrecognized image '$image_id' *" );
+  }
+  
+  return $im;
+}
+
+sub do_popimage {
+  my ($self, $image_id, $class, $images) = @_;
+
+  my ($im, $msg) = $self->get_image($image_id, $images);
+  $im
+    or return $msg;
+
+  return $self->do_popimage_low($im, $class);
+}
+
 # note: this is called by BSE::Formatter::thumbimage(), update that if
 # this is changed
 sub do_thumbimage {
-  my ($self, $geo_id, $image_id, $field, $images, $rcurrent) = @_;
+  my ($self, $geo_id, $image_id, $field, $images, $current) = @_;
 
   my $im;
-  if ($image_id eq '-' && $rcurrent) {
-    $im = $rcurrent
+  if ($image_id eq '-' && $current) {
+    $im = $current
       or return "** No current image in images iterator **"
   }
-  elsif ($image_id =~ /^\d+$/) {
-    $image_id >= 1 || $image_id <= @$images
-      or return "** Out of range image index **";
-
-    $im = $images->[$image_id-1];
-  }
-  elsif ($image_id =~ /^[^\W\d]\w*$/) {
-    ($im) = grep $_->{name} eq $image_id, @$images
-      or return "** Unknown images identifier $image_id **";
+  else {
+    ($im, my $msg) = $self->get_image($image_id, $images);
+    $im
+      or return $msg;
   }
 
-  return $self->_thumbimage_low($geo_id, $im, $field, $self->{cfg});
+  return $self->_sthumbimage_low($geo_id, $im, $field);
 }
 
 sub generate {
@@ -677,6 +784,23 @@ sub tag_movekid {
   return make_arrows($self->{cfg}, $down_url, $up_url, $refreshto, $img_prefix);
 }
 
+sub _find_articles {
+  my ($self, $article_id, $article, @rest) = @_;
+
+  if ($article_id eq 'article') {
+    return $article;
+  }
+  elsif ($article_id eq 'children') {
+    return $article->all_visible_kids;
+  }
+  elsif ($article_id eq 'parent') {
+    return $article->parent;
+  }
+  else {
+    return $self->SUPER::_find_articles($article_id, $article, @rest);
+  }
+}
+
 1;
 
 __END__