summaryrefslogtreecommitdiff
path: root/LedgerSMB/Template.pm
blob: 93254df192c815839de592789fa421883c55b396 (plain)
  1. #=====================================================================
  2. #
  3. # Template support module for LedgerSMB
  4. # LedgerSMB::Template
  5. #
  6. # LedgerSMB
  7. # Small Medium Business Accounting software
  8. # http://www.ledgersmb.org/
  9. #
  10. #
  11. # Copyright (C) 2007
  12. # This work contains copyrighted information from a number of sources all used
  13. # with permission. It is released under the GNU General Public License
  14. # Version 2 or, at your option, any later version. See COPYRIGHT file for
  15. # details.
  16. #
  17. #
  18. #======================================================================
  19. # This package contains template related functions:
  20. #
  21. #
  22. #====================================================================
  23. use Error qw(:try);
  24. use Template;
  25. use LedgerSMB::Sysconfig;
  26. package LedgerSMB::Template;
  27. sub new {
  28. my $class = shift;
  29. my $self = {};
  30. $self->{myconfig} = shift;
  31. $self->{template} = shift;
  32. $self->{format} = shift;
  33. $self->{language} = shift;
  34. $self->{output} = '';
  35. bless $self, $class;
  36. return $self;
  37. }
  38. sub valid_language {
  39. my $self = shift;
  40. # XXX Actually perform validity checks
  41. return 1;
  42. }
  43. sub render {
  44. my $self = shift;
  45. my $vars = shift;
  46. my $template;
  47. if ( not defined $self->{language} ) {
  48. $template = Template->new(
  49. {
  50. INCLUDE_PATH => $self->{'myconfig'}->{'templates'},
  51. START_TAG => quotemeta('<?lsmb'),
  52. END_TAG => quotemeta('?>'),
  53. DELIMITER => ';',
  54. }
  55. ) || throw Error::Simple Template->error();
  56. }
  57. elsif ( $self->valid_language() ) {
  58. $template = Template->new(
  59. {
  60. INCLUDE_PATH =>
  61. "$self->{'myconfig'}->{'templates'}/$self->{language};$self->{'myconfig'}->{'templates'}",
  62. START_TAG => quotemeta('<?lsmb'),
  63. END_TAG => quotemeta('?>'),
  64. DELIMITER => ';',
  65. }
  66. ) || throw Error::Simple Template->error();
  67. }
  68. else {
  69. throw Error::Simple 'Invalid language';
  70. }
  71. eval "require LedgerSMB::Template::$self->{format}";
  72. if ($@) {
  73. throw Error::Simple $@;
  74. }
  75. my $cleanvars =
  76. &{"LedgerSMB::Template::$self->{format}::preprocess"}($vars);
  77. if (
  78. not $template->process(
  79. &{"LedgerSMB::Template::$self->{format}::get_template"}(
  80. $self->{template} ),
  81. $cleanvars,
  82. \$self->{output},
  83. binmode => ':utf8'
  84. )
  85. )
  86. {
  87. throw Error::Simple $template->error();
  88. }
  89. &{"LedgerSMB::Template::$self->{format}::postprocess"}($self);
  90. return $self->{output};
  91. }
  92. 1;
p;& @list > $params{show}) {
  • @list=@list[0..$params{show} - 1];
  • }
  • add_depends($params{page}, $params{pages});
  • my $rssurl=rsspage(basename($params{page}));
  • my $atomurl=atompage(basename($params{page}));
  • my $ret="";
  • if (exists $params{rootpage} && $config{cgiurl}) {
  • # Add a blog post form, with feed buttons.
  • my $formtemplate=template("blogpost.tmpl", blind_cache => 1);
  • $formtemplate->param(cgiurl => $config{cgiurl});
  • $formtemplate->param(rootpage => $params{rootpage});
  • $formtemplate->param(rssurl => $rssurl) if $feeds && $rss;
  • $formtemplate->param(atomurl => $atomurl) if $feeds && $atom;
  • $ret.=$formtemplate->output;
  • }
  • elsif ($feeds) {
  • # Add feed buttons.
  • my $linktemplate=template("feedlink.tmpl", blind_cache => 1);
  • $linktemplate->param(rssurl => $rssurl) if $rss;
  • $linktemplate->param(atomurl => $atomurl) if $atom;
  • $ret.=$linktemplate->output;
  • }
  • my $template=template(
  • ($archive ? "inlinepagetitle.tmpl" : "inlinepage.tmpl"),
  • blind_cache => 1,
  • ) unless $raw;
  • foreach my $page (@list) {
  • my $file = $pagesources{$page};
  • my $type = pagetype($file);
  • if (! $raw || ($raw && ! defined $type)) {
  • # Get the content before populating the template,
  • # since getting the content uses the same template
  • # if inlines are nested.
  • # TODO: if $archive=1, the only reason to do this
  • # is to let the meta plugin get page title info; so stop
  • # calling this next line then once the meta plugin can
  • # store that accross runs (also tags plugin).
  • my $content=get_inline_content($page, $params{destpage});
  • # Don't use htmllink because this way the title is separate
  • # and can be overridden by other plugins.
  • my $link=bestlink($params{page}, $page);
  • $link=htmlpage($link) if defined $type;
  • $link=abs2rel($link, dirname($params{destpage}));
  • $template->param(pageurl => $link);
  • $template->param(title => pagetitle(basename($page)));
  • $template->param(content => $content);
  • $template->param(ctime => displaytime($pagectime{$page}));
  • if ($actions) {
  • my $file = $pagesources{$page};
  • my $type = pagetype($file);
  • if ($config{discussion}) {
  • $template->param(have_actions => 1);
  • $template->param(discussionlink => htmllink($page, $page, "Discussion", 1, 1));
  • }
  • if (length $config{cgiurl} && defined $type) {
  • $template->param(have_actions => 1);
  • $template->param(editurl => cgiurl(do => "edit", page => $page));
  • }
  • }
  • run_hooks(pagetemplate => sub {
  • shift->(page => $page, destpage => $params{page},
  • template => $template,);
  • });
  • $ret.=$template->output;
  • $template->clear_params;
  • }
  • else {
  • if (defined $type) {
  • $ret.="\n".
  • linkify($page, $params{page},
  • preprocess($page, $params{page},
  • filter($page,
  • readfile(srcfile($file)))));
  • }
  • }
  • }
  • if ($feeds && $rss) {
  • will_render($params{page}, rsspage($params{page}));
  • writefile(rsspage($params{page}), $config{destdir},
  • genfeed("rss", $rssurl, $desc, $params{page}, @list));
  • $toping{$params{page}}=1 unless $config{rebuild};
  • $feedlinks{$params{destpage}}=qq{<link rel="alternate" type="application/rss+xml" title="RSS" href="$rssurl" />};
  • }
  • if ($feeds && $atom) {
  • will_render($params{page}, atompage($params{page}));
  • writefile(atompage($params{page}), $config{destdir},
  • genfeed("atom", $atomurl, $desc, $params{page}, @list));
  • $toping{$params{page}}=1 unless $config{rebuild};
  • $feedlinks{$params{destpage}}=qq{<link rel="alternate" type="application/atom+xml" title="Atom" href="$atomurl" />};
  • }
  • return $ret;
  • } #}}}
  • sub pagetemplate_inline (@) { #{{{
  • my %params=@_;
  • my $page=$params{page};
  • my $template=$params{template};
  • $template->param(feedlinks => $feedlinks{$page})
  • if exists $feedlinks{$page} && $template->query(name => "feedlinks");
  • } #}}}
  • sub get_inline_content ($$) { #{{{
  • my $page=shift;
  • my $destpage=shift;
  • my $file=$pagesources{$page};
  • my $type=pagetype($file);
  • if (defined $type) {
  • return htmlize($page, $type,
  • linkify($page, $destpage,
  • preprocess($page, $destpage,
  • filter($page,
  • readfile(srcfile($file))))));
  • }
  • else {
  • return "";
  • }
  • } #}}}
  • sub date_822 ($) { #{{{
  • my $time=shift;
  • eval q{use POSIX};
  • my $lc_time= POSIX::setlocale(&POSIX::LC_TIME);
  • POSIX::setlocale(&POSIX::LC_TIME, "C");
  • my $ret=POSIX::strftime("%a, %d %b %Y %H:%M:%S %z", localtime($time));
  • POSIX::setlocale(&POSIX::LC_TIME, $lc_time);
  • return $ret;
  • } #}}}
  • sub date_3339 ($) { #{{{
  • my $time=shift;
  • eval q{use POSIX};
  • my $lc_time= POSIX::setlocale(&POSIX::LC_TIME);
  • POSIX::setlocale(&POSIX::LC_TIME, "C");
  • my $ret=POSIX::strftime("%Y-%m-%dT%H:%M:%SZ", localtime($time));
  • POSIX::setlocale(&POSIX::LC_TIME, $lc_time);
  • return $ret;
  • } #}}}
  • sub absolute_urls ($$) { #{{{
  • # sucky sub because rss sucks
  • my $content=shift;
  • my $url=shift;
  • $url=~s/[^\/]+$//;
  • $content=~s/<a\s+href="(?![^:]+:\/\/)([^"]+)"/<a href="$url$1"/ig;
  • $content=~s/<img\s+src="(?![^:]+:\/\/)([^"]+)"/<img src="$url$1"/ig;
  • return $content;
  • } #}}}
  • sub rsspage ($) { #{{{
  • my $page=shift;
  • return $page.".rss";
  • } #}}}
  • sub atompage ($) { #{{{
  • my $page=shift;
  • return $page.".atom";
  • } #}}}
  • sub genfeed ($$$$@) { #{{{
  • my $feedtype=shift;
  • my $feedurl=shift;
  • my $feeddesc=shift;
  • my $page=shift;
  • my @pages=@_;
  • my $url=URI->new(encode_utf8($config{url}."/".htmlpage($page)));
  • my $itemtemplate=template($feedtype."item.tmpl", blind_cache => 1);
  • my $content="";
  • my $lasttime = 0;
  • foreach my $p (@pages) {
  • my $u=URI->new(encode_utf8($config{url}."/".htmlpage($p)));
  • $itemtemplate->param(
  • title => pagetitle(basename($p)),
  • url => $u,
  • permalink => $u,
  • date_822 => date_822($pagectime{$p}),
  • date_3339 => date_3339($pagectime{$p}),
  • );
  • my $pcontent = absolute_urls(get_inline_content($p, $page), $url);
  • if ($itemtemplate->query(name => "enclosure")) {
  • my $file=$pagesources{$p};
  • my $type=pagetype($file);
  • if (defined $type) {
  • $itemtemplate->param(content => $pcontent);
  • }
  • else {
  • my ($a, $b, $c, $d, $e, $f, $g, $size) = stat(srcfile($file));
  • my $mime="unknown";
  • eval q{use File::MimeInfo};
  • if (! $@) {
  • $mime = mimetype($file);
  • }
  • $itemtemplate->param(
  • enclosure => $u,
  • type => $mime,
  • length => $size,
  • );
  • }
  • }
  • else {
  • $itemtemplate->param(content => $pcontent);
  • }
  • run_hooks(pagetemplate => sub {
  • shift->(page => $p, destpage => $page,
  • template => $itemtemplate);
  • });
  • $content.=$itemtemplate->output;
  • $itemtemplate->clear_params;
  • $lasttime = $pagectime{$p} if $pagectime{$p} > $lasttime;
  • }
  • my $template=template($feedtype."page.tmpl", blind_cache => 1);
  • $template->param(
  • title => $page ne "index" ? pagetitle($page) : $config{wikiname},