From 599fe373187cbd9d49e00d30aa8ad9dae16c1b81 Mon Sep 17 00:00:00 2001 From: Tony Cook Date: Mon, 28 May 2012 15:40:08 +1000 Subject: [PATCH] allow use of the new template system from static pages --- .gitignore | 3 + site/cgi-bin/modules/Article.pm | 117 +++++++++++++++++++++- site/cgi-bin/modules/BSE/Regen.pm | 9 +- site/cgi-bin/modules/BSE/TB/SiteCommon.pm | 64 +++++++++++- site/cgi-bin/modules/BSE/TB/TagOwner.pm | 93 ++++++++++++++++- site/cgi-bin/modules/BSE/Template.pm | 6 +- site/cgi-bin/modules/Generate.pm | 48 ++++++++- site/cgi-bin/modules/Generate/Article.pm | 7 +- site/docs/makedocs | 3 + site/templates/base.tmpl | 44 ++++---- t/t20gen.t | 8 +- 11 files changed, 364 insertions(+), 38 deletions(-) diff --git a/.gitignore b/.gitignore index 8425a88b..47549661 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,9 @@ INSTALL.html INSTALL.txt site/cgi-bin/modules/BSE/Modules.pm site/cgi-bin/modules/BSE/Version.pm +site/docs/Article.html +site/docs/BSE::TB::SiteCommon.html +site/docs/BSE::TB::TagOwner.html site/docs/BSE::UI::Affiliate.html site/docs/Generate.html site/docs/Generate::Article.html diff --git a/site/cgi-bin/modules/Article.pm b/site/cgi-bin/modules/Article.pm index ce623223..f011ad2c 100644 --- a/site/cgi-bin/modules/Article.pm +++ b/site/cgi-bin/modules/Article.pm @@ -8,7 +8,29 @@ use vars qw/@ISA/; @ISA = qw/Squirrel::Row BSE::TB::SiteCommon BSE::TB::TagOwner/; use Carp 'confess'; -our $VERSION = "1.011"; +our $VERSION = "1.012"; + +=head1 NAME + +Article - article objects for BSE. + +=head1 SYNOPSIS + + use BSE::API qw(bse_make_article); + + my $article = bse_make_article(...) + + my $article = Articles->getByPkey($id); + +=head1 DESCRIPTION + +Implements the base article object for BSE. + +=head1 USEFUL METHODS + +=over + +=cut sub columns { return qw/id parentid displayOrder title titleImage body @@ -32,6 +54,12 @@ sub numeric { customInt1 customInt2 customInt3 customInt4 menu); } +=item section + +Return the article's section. + +=cut + sub section { my ($self) = @_; @@ -44,6 +72,12 @@ sub section { return $section; } +=item parent + +Return the article's parent. + +=cut + sub parent { my ($self) = @_; $self->{parentid} == -1 and return; @@ -74,6 +108,12 @@ sub update_dynamic { $self->{cached_dynamic} = $dynamic; } +=item is_dynamic + +Return true if the article is rendered dynamically. + +=cut + sub is_dynamic { $_[0]{cached_dynamic}; } @@ -307,6 +347,12 @@ sub link { return $link; } +=item admin + +Return the admin link for the article. + +=cut + sub admin { my ($self) = @_; @@ -354,6 +400,57 @@ sub is_released { return $self->release le _expire_release_datetime(); } +=item listed_in_menu + +Return true if the article should be listed in menus. + +=cut + +sub listed_in_menu { + my $self = shift; + + return $self->listed == 1; +} + +=item ancestors + +Returns a list of ancestors of self. + +=cut + +sub ancestors { + my ($self) = @_; + + unless ($self->{_ancestors}) { + my @ancestors; + my $work = $self; + while ($work->parentid != -1) { + $work = $work->parent; + push @ancestors, $work; + } + + $self->{_ancestors} = \@ancestors; + } + + return @{$self->{_ancestors}}; +} + +=item is_descendant_of($ancestor) + +Return true if the supplied article is a descendant of self. + +=cut + +sub is_descendant_of { + my ($self, $ancestor) = @_; + + for my $anc ($self->ancestors) { + return 1 if $anc->id == $ancestor->id; + } + + return 0; +} + sub restricted_methods { my ($self, $name) = @_; @@ -362,3 +459,21 @@ sub restricted_methods { } 1; + +__END__ + +=back + +=head1 BASE CLASSES + +L + +L + +L + +=head1 AUTHOR + +Tony Cook + +=cut diff --git a/site/cgi-bin/modules/BSE/Regen.pm b/site/cgi-bin/modules/BSE/Regen.pm index 961475be..2447b6d7 100644 --- a/site/cgi-bin/modules/BSE/Regen.pm +++ b/site/cgi-bin/modules/BSE/Regen.pm @@ -10,7 +10,7 @@ use Carp qw(confess); use BSE::WebUtil qw(refresh_to_admin); use BSE::Util::HTML; -our $VERSION = "1.005"; +our $VERSION = "1.006"; # returns non-zero if the Regenerate button should work sub generate_button { @@ -316,7 +316,9 @@ sub _common_one_extra { }; } - my $content = BSE::Template->get_page($extra->{base}, $cfg, \%acts); + my $content = BSE::Template->get_page($extra->{base}, $cfg, \%acts, + undef, undef, $gen->variables); + return wantarray ? ( $content, $article ) : $content; } @@ -390,7 +392,8 @@ sub generate_base { }; } $progress->($extra, "Generating $extra->{name}"); - my $content = BSE::Template->get_page($extra->{base}, $cfg, \%acts); + my $content = BSE::Template->get_page($extra->{base}, $cfg, \%acts, + undef, undef, $gen->variables); my $outname = $extra->{outpath} . "/". $extra->{name}; my $workname = $outname . ".work"; _write_text($workname, $content, $cfg); diff --git a/site/cgi-bin/modules/BSE/TB/SiteCommon.pm b/site/cgi-bin/modules/BSE/TB/SiteCommon.pm index 754c8927..42876718 100644 --- a/site/cgi-bin/modules/BSE/TB/SiteCommon.pm +++ b/site/cgi-bin/modules/BSE/TB/SiteCommon.pm @@ -2,7 +2,26 @@ package BSE::TB::SiteCommon; use strict; use Carp qw(confess); -our $VERSION = "1.003"; +our $VERSION = "1.005"; + +=head1 NAME + +BSE::TB::SiteCommon - methods common to the site and article objects + +=head1 SYNOPSIS + + my @steps = $article->set_parents; + my @sections = $site->children; + +=head1 DESCRIPTION + +Provides methods common to the Article and BSE::TB::Site objects. + +=head1 USEFUL METHODS + +=over + +=cut sub step_parents { my ($self) = @_; @@ -100,6 +119,37 @@ sub all_visible_catalogs { return grep $_->{generator} eq "Generate::Catalog", $self->all_visible_kids; } +sub visible_kids { + my ($self) = @_; + + return Articles->listedChildren($self->{id}); +} + +=item menu_kids + +Returns a list of children meant to be listed in menus. + +=cut + +sub menu_kids { + my ($self) = @_; + + return grep $_->listed_in_menu, $self->visible_kids; +} + + +=item menu_kids + +Returns a list of allkids meant to be listed in menus. + +=cut + +sub all_menu_kids { + my ($self) = @_; + + return grep $_->listed_in_menu, $self->all_visible_kids; +} + sub images { my ($self) = @_; require BSE::TB::Images; @@ -109,7 +159,7 @@ sub images { sub children { my ($self) = @_; - return sort { $b->{displayOrder} <=> $b->{displayOrder} } + return sort { $b->{displayOrder} <=> $a->{displayOrder} } Articles->children($self->{id}); } @@ -324,3 +374,13 @@ sub set_image_order { } 1; + +__END__ + +=back + +=head1 AUTHOR + +Tony Cook + +=cut diff --git a/site/cgi-bin/modules/BSE/TB/TagOwner.pm b/site/cgi-bin/modules/BSE/TB/TagOwner.pm index d1127e94..b226991b 100644 --- a/site/cgi-bin/modules/BSE/TB/TagOwner.pm +++ b/site/cgi-bin/modules/BSE/TB/TagOwner.pm @@ -6,7 +6,40 @@ use strict; use BSE::TB::Tags; use BSE::TB::TagMembers; -our $VERSION = "1.001"; +our $VERSION = "1.002"; + +=head1 NAME + +BSE::TB::TagOwner - mixin for objects with tags + +=head1 SYNOPSIS + + my $article = ...; + + $article->set_tags([ qw/tag1 tag2/ ], \$error); + $article->remove_tags; + + my @tags = $article->tag_objects; + my @tag_names = $article->tags; + my @tag_ids = $article->tag_ids; + + if ($article->has_tags([ "tag1", "tag2" ])) { + ... + } + +=head1 DESCRIPTION + +This class is a mix-in that implements tags for the mixed-into object. + +=head1 METHODS PROVIDED + +=over + +=item set_tags(\@tags, \$error) + +Set the specified tags on the object, replacing all existing tags. + +=cut sub set_tags { my ($self, $rtags, $rerror) = @_; @@ -69,31 +102,60 @@ sub set_tags { return 1; } -# remove all tags +=item remove_tags + +Remove all tags from the object. + +=cut + sub remove_tags { my ($self) = @_; BSE::TB::TagMembers->remove_owned_by($self); } +=item tag_objects + +Return all existing tags on the object as tag objects. + +=cut + sub tag_objects { my ($self) = @_; return BSE::TB::Tags->getSpecial(object_tags => $self->tag_owner_type, $self->id); } +=item tags + +Returns all existing tags on the object as tag names. + +=cut + sub tags { my ($self) = @_; return map $_->name, $self->tag_objects; } +=item tag_ids + +Returns all existing tags on the object as tag ids. + +=cut + sub tag_ids { my ($self) = @_; return map $_->{id}, BSE::DB->single->run("Tag_ids.by_owner", $self->tag_owner_type, $self->id); } +=item has_tags(\@tags) + +Check that all of the specified tags are on the object. + +=cut + sub has_tags { my ($self, $rtags) = @_; @@ -116,3 +178,30 @@ sub has_tags { } 1; + +__END__ + +=back + +=head1 REQUIRED METHODS + +These need to be implemented by the class that wants tags. + +=over + +=item tag_owner_type + +Return a short constant string identifying owner class of the tags. + +=item id + +The numeric id of the specific owner object of the tags. + +=back + +=head1 AUTHOR + +Tony Cook + +=cut + diff --git a/site/cgi-bin/modules/BSE/Template.pm b/site/cgi-bin/modules/BSE/Template.pm index 113e0f29..b62556b4 100644 --- a/site/cgi-bin/modules/BSE/Template.pm +++ b/site/cgi-bin/modules/BSE/Template.pm @@ -4,7 +4,7 @@ use Squirrel::Template; use Carp qw(confess cluck); use Config (); -our $VERSION = "1.006"; +our $VERSION = "1.007"; sub templater { my ($class, $cfg, $rsets) = @_; @@ -75,11 +75,11 @@ sub get_page { } sub replace { - my ($class, $source, $cfg, $acts) = @_; + my ($class, $source, $cfg, $acts, $vars) = @_; my $obj = $class->templater($cfg); - $obj->replace_template($source, $acts); + $obj->replace_template($source, $acts, undef, undef, $vars); } sub charset { diff --git a/site/cgi-bin/modules/Generate.pm b/site/cgi-bin/modules/Generate.pm index e0cb0bf2..35a5efc2 100644 --- a/site/cgi-bin/modules/Generate.pm +++ b/site/cgi-bin/modules/Generate.pm @@ -8,10 +8,11 @@ use BSE::Util::HTML; use BSE::Util::Tags qw(tag_article); use BSE::CfgInfo qw(custom_class); use BSE::Util::Iterate; +use BSE::TB::Site; use base 'BSE::ThumbLow'; use base 'BSE::TagFormats'; -our $VERSION = "1.006"; +our $VERSION = "1.007"; my $excerptSize = 300; @@ -24,13 +25,56 @@ sub new { } $opts{maxdepth} = $EMBED_MAX_DEPTH unless exists $opts{maxdepth}; $opts{depth} = 0 unless $opts{depth}; - return bless \%opts, $class; + $opts{vars} = + { + cfg => $opts{cfg}, + bse => + { + site => BSE::TB::Site->new, + url => + ($opts{admin} || $opts{admin_links} + ? sub { $_[0]->admin } + : sub { $_[0]->link } + ), + admin => $opts{admin}, + admin_links => $opts{admin_links}, + dumper => sub { + require Data::Dumper; + return escape_html(Data::Dumper::Dumper(shift)); + }, + }, + }; + my $self = bless \%opts, $class; + $self->set_variable_class(articles => "Articles"); + + return $self; } sub cfg { $_[0]{cfg}; } +sub set_variable { + my ($self, $name, $value) = @_; + + $self->{vars}{$name} = $value; + + return 1; +} + +sub set_variable_class { + my ($self, $name, $class) = @_; + + require Squirrel::Template; + $self->set_variable($name => Squirrel::Template::Expr::WrapClass->new($class)); +} + +sub variables { + my ($self) = @_; + + return $self->{vars}; +} + # replace commonly used characters # like MS dumb-quotes # unfortunately some browsers^W^Wnetscape don't support the entities yet diff --git a/site/cgi-bin/modules/Generate/Article.pm b/site/cgi-bin/modules/Generate/Article.pm index 6c04b343..01fa0c98 100644 --- a/site/cgi-bin/modules/Generate/Article.pm +++ b/site/cgi-bin/modules/Generate/Article.pm @@ -15,7 +15,7 @@ use BSE::Arrows; use Carp 'confess'; use BSE::Util::Iterate; -our $VERSION = "1.003"; +our $VERSION = "1.004"; my $excerptSize = 300; @@ -61,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 @@ -362,6 +363,8 @@ sub baseActs { 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}); diff --git a/site/docs/makedocs b/site/docs/makedocs index 358a7eb6..6ec7f437 100644 --- a/site/docs/makedocs +++ b/site/docs/makedocs @@ -7,7 +7,10 @@ use strict; my @targets = ( 'access.html', + 'Article.html', 'bse.html', + 'BSE::TB::SiteCommon.html', + 'BSE::TB::TagOwner.html', 'bugs.html', 'templates.html', 'Generate.html', diff --git a/site/templates/base.tmpl b/site/templates/base.tmpl index 5c529a85..e54a66bf 100644 --- a/site/templates/base.tmpl +++ b/site/templates/base.tmpl @@ -113,55 +113,55 @@ <:include include/cart_sidebar.tmpl:> <:or Cfg:><:eif Cfg:> <:or Dynamic:> - <:iterator begin level1:> + <:.set level1_menu = [ bse.site.menu_kids ] :> + <:.for level1 in level1_menu :> - <:if Ancestor level1:> + <:.if article.is_descendant_of(level1) :> -<:or Ancestor:> -<:eif Ancestor:> +<:.end if:>
- <:if Ancestor level1:> + <:.if article.is_descendant_of(level1):> - + - <:or Ancestor:> + <:.else:> - + - <:eif Ancestor:> + <:.end if:>
 <:ifLevel1 link:><:or:><:eif:><:level1 - title:><:ifLevel1 link:><:or:><:eif:>  <:.if level1.link:><:.end if:><:= level1.title + |html :><:.if level1.link:><:.end if:>
 <:ifLevel1 link:><:or:><:eif:><:level1 - title:><:ifLevel1 link:><:or:><:eif:>  <:.if level1.link:><:.end if:><:= level1.title |html:><:.if level1.link:><:.end if:>
- <:if Level2:> + <:.set level2_menu = [ level1.menu_kids ] :> + <:# = bse.dumper(level2_menu) :> + <:.if level2_menu.size != 0:> - <:iterator begin level2:> - <:ifAncestor level2:> + <:.for level2 in level2_menu:> + <:.if article.is_descendant_of(level2) :> - - <:or:> + <:.else:> - - <:eif:> - <:iterator end level2:> + <:.end if:> + <:.end for:>
<:level2 title:> + <:= level2.title |html:>
<:level2 title:> + <:= level2.title |html:>
- <:or Level2:> - <:eif Level2:> + <:.end if:>
spacer
-<:iterator separator level1:><:iterator end level1:> +<:.end for:> <:eif Dynamic:> <:embed 5:> diff --git a/t/t20gen.t b/t/t20gen.t index b9147f46..85269907 100644 --- a/t/t20gen.t +++ b/t/t20gen.t @@ -76,11 +76,17 @@ template_test "children_of", $top, <{id}:><: ofchild title:> <:iterator end children_of:> +<:-.set myart = articles.getByPkey($parent->{id}):> +<:-.for a in [ myart.visible_kids ]:> +<:-= a.title |html :> +<:.end for-:> TEMPLATE Three Two One - +Three +Two +One EXPECTED template_test "allkids_of", $top, <