@@ -, +, @@ switch, hide it behind a syspref --- C4/Letters.pm | 151 +++++++++++---------- installer/data/mysql/atomicupdate/bug_14757.sql | 4 + installer/data/mysql/kohastructure.sql | 1 + installer/data/mysql/sysprefs.sql | 1 + .../prog/en/modules/admin/preferences/labs.pref | 9 ++ .../intranet-tmpl/prog/en/modules/tools/letter.tt | 13 ++ t/db_dependent/Letters/TemplateToolkit.t | 2 +- tools/letter.pl | 10 +- 8 files changed, 118 insertions(+), 73 deletions(-) create mode 100644 installer/data/mysql/atomicupdate/bug_14757.sql --- a/C4/Letters.pm +++ a/C4/Letters.pm @@ -124,7 +124,7 @@ sub GetLetterTemplates { my $dbh = C4::Context->dbh; my $letters = $dbh->selectall_hashref( q| - SELECT module, code, branchcode, name, is_html, title, content, message_transport_type + SELECT module, code, branchcode, name, is_html, title, content, message_transport_type, is_tt FROM letter WHERE module = ? AND code = ? @@ -642,89 +642,104 @@ sub GetPreparedLetter { or warn( "No $module $letter_code letter transported by " . $mtt ), return; - my $tables = $params{tables}; + my $tables = $params{tables}; my $substitute = $params{substitute}; - my $repeat = $params{repeat}; + my $repeat = $params{repeat}; + $tables || $substitute || $repeat or carp( "ERROR: nothing to substitute - both 'tables' and 'substitute' are empty" ), return; - my $want_librarian = $params{want_librarian}; - if ($substitute) { - while ( my ($token, $val) = each %$substitute ) { - if ( $token eq 'items.content' ) { - $val =~ s|\n|
|g if $letter->{is_html}; - } + my $userenv = C4::Context->userenv; - $letter->{title} =~ s/<<$token>>/$val/g; - $letter->{content} =~ s/<<$token>>/$val/g; - } + if ( $letter->{is_tt} ) { + $letter->{content} = _process_tt( + { + content => $letter->{content}, + tables => $tables, + tt_params => { + today => dt_from_string(), + librarian => { + firstname => $userenv->{firstname}, + surname => $userenv->{surname}, + emailaddress => $userenv->{emailaddress}, + }, + } + } + ); } + else { + my $want_librarian = $params{want_librarian}; - my $OPACBaseURL = C4::Context->preference('OPACBaseURL'); - $letter->{content} =~ s/<>/$OPACBaseURL/go; + if ($substitute) { + while ( my ($token, $val) = each %$substitute ) { + if ( $token eq 'items.content' ) { + $val =~ s|\n|
|g if $letter->{is_html}; + } - if ($want_librarian) { - # parsing librarian name - my $userenv = C4::Context->userenv; - $letter->{content} =~ s/<>/$userenv->{firstname}/go; - $letter->{content} =~ s/<>/$userenv->{surname}/go; - $letter->{content} =~ s/<>/$userenv->{emailaddress}/go; - } + $letter->{title} =~ s/<<$token>>/$val/g; + $letter->{content} =~ s/<<$token>>/$val/g; + } + } - my ($repeat_no_enclosing_tags, $repeat_enclosing_tags); + my $OPACBaseURL = C4::Context->preference('OPACBaseURL'); + $letter->{content} =~ s/<>/$OPACBaseURL/go; - if ($repeat) { - if (ref ($repeat) eq 'ARRAY' ) { - $repeat_no_enclosing_tags = $repeat; - } else { - $repeat_enclosing_tags = $repeat; + if ($want_librarian) { + # parsing librarian name + $letter->{content} =~ s/<>/$userenv->{firstname}/go; + $letter->{content} =~ s/<>/$userenv->{surname}/go; + $letter->{content} =~ s/<>/$userenv->{emailaddress}/go; } - } - if ($repeat_enclosing_tags) { - while ( my ($tag, $tag_tables) = each %$repeat_enclosing_tags ) { - if ( $letter->{content} =~ m!<$tag>(.*)!s ) { - my $subcontent = $1; - my @lines = map { - my %subletter = ( title => '', content => $subcontent ); - _substitute_tables( \%subletter, $_ ); - $subletter{content}; - } @$tag_tables; - $letter->{content} =~ s!<$tag>.*!join( "\n", @lines )!se; + my ($repeat_no_enclosing_tags, $repeat_enclosing_tags); + + if ($repeat) { + if (ref ($repeat) eq 'ARRAY' ) { + $repeat_no_enclosing_tags = $repeat; + } else { + $repeat_enclosing_tags = $repeat; } } - } - - if ($tables) { - _substitute_tables( $letter, $tables ); - } - if ($repeat_no_enclosing_tags) { - if ( $letter->{content} =~ m/[^\n]*<<.*>>[^\n]*/so ) { - my $line = $&; - my $i = 1; - my @lines = map { - my $c = $line; - $c =~ s/<>/$i/go; - foreach my $field ( keys %{$_} ) { - $c =~ s/(<<[^\.]+.$field>>)/$_->{$field}/; + if ($repeat_enclosing_tags) { + while ( my ($tag, $tag_tables) = each %$repeat_enclosing_tags ) { + if ( $letter->{content} =~ m!<$tag>(.*)!s ) { + my $subcontent = $1; + my @lines = map { + my %subletter = ( title => '', content => $subcontent ); + _substitute_tables( \%subletter, $_ ); + $subletter{content}; + } @$tag_tables; + $letter->{content} =~ s!<$tag>.*!join( "\n", @lines )!se; } - $i++; - $c; - } @$repeat_no_enclosing_tags; + } + } - my $replaceby = join( "\n", @lines ); - $letter->{content} =~ s/\Q$line\E/$replaceby/s; + if ($tables) { + _substitute_tables( $letter, $tables ); } - } - $letter->{content} = _process_tt( - { - content => $letter->{content}, - tables => $tables, + if ($repeat_no_enclosing_tags) { + if ( $letter->{content} =~ m/[^\n]*<<.*>>[^\n]*/so ) { + my $line = $&; + my $i = 1; + my @lines = map { + my $c = $line; + $c =~ s/<>/$i/go; + foreach my $field ( keys %{$_} ) { + $c =~ s/(<<[^\.]+.$field>>)/$_->{$field}/; + } + $i++; + $c; + } @$repeat_no_enclosing_tags; + + my $replaceby = join( "\n", @lines ); + $letter->{content} =~ s/\Q$line\E/$replaceby/s; + } } - ); + + } $letter->{content} =~ s/<<\S*>>//go; #remove any stragglers @@ -1337,8 +1352,9 @@ sub _set_message_status { sub _process_tt { my ( $params ) = @_; - my $content = $params->{content}; - my $tables = $params->{tables}; + my $content = $params->{content}; + my $tables = $params->{tables}; + my $tt_params = $params->{tt_params}; my $use_template_cache = C4::Context->config('template_cache_dir') && defined $ENV{GATEWAY_INTERFACE}; my $template = Template->new( @@ -1353,7 +1369,8 @@ sub _process_tt { } ) or die Template->error(); - my $tt_params = _get_tt_params( $tables ); + my $tt_objects = _get_tt_params( $tables ); + $tt_params = { %$tt_params, %$tt_objects }; my $output; $template->process( \$content, $tt_params, \$output ) || croak "ERROR PROCESSING TEMPLATE: " . $template->error(); @@ -1474,8 +1491,6 @@ sub _get_tt_params { } } - $params->{today} = dt_from_string(); - return $params; } --- a/installer/data/mysql/atomicupdate/bug_14757.sql +++ a/installer/data/mysql/atomicupdate/bug_14757.sql @@ -0,0 +1,4 @@ +ALTER TABLE letter ADD is_tt TINYINT(1) NOT NULL DEFAULT 0 AFTER message_transport_type; + +INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, `type` ) VALUES +('TemplateToolkitNotices',0,'','Enable the ability to use Template Toolkit syntax in slips and notices','YesNo'); --- a/installer/data/mysql/kohastructure.sql +++ a/installer/data/mysql/kohastructure.sql @@ -1428,6 +1428,7 @@ CREATE TABLE `letter` ( -- table for all notice templates in Koha `title` varchar(200) NOT NULL default '', -- subject line of the notice `content` text, -- body text for the notice or slip `message_transport_type` varchar(20) NOT NULL DEFAULT 'email', -- transport type for this notice + `is_tt` TINYINT(1) NOT NULL DEFAULT 0, -- controls if notice should be processed as template toolkit syntax PRIMARY KEY (`module`,`code`, `branchcode`, `message_transport_type`), CONSTRAINT `message_transport_type_fk` FOREIGN KEY (`message_transport_type`) REFERENCES `message_transport_types` (`message_transport_type`) ON DELETE CASCADE ON UPDATE CASCADE --- a/installer/data/mysql/sysprefs.sql +++ a/installer/data/mysql/sysprefs.sql @@ -472,6 +472,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('TagsModeration','0','','Require tags from patrons to be approved before becoming visible.','YesNo'), ('TagsShowOnDetail','10','','Number of tags to display on detail page. 0 is off.','Integer'), ('TagsShowOnList','6','','Number of tags to display on search results list. 0 is off.','Integer'), +('TemplateToolkitNotices',0,'','Enable the ability to use Template Toolkit syntax in slips and notices','YesNo'), ('template','prog','','Define the preferred staff interface template','Themes'), ('ThingISBN','0','','Use with FRBRizeEditions. If ON, Koha will use the ThingISBN web service in the Editions tab on the detail pages.','YesNo'), ('TimeFormat','24hr','12hr|24hr','Defines the global time format for visual output.','Choice'), --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/labs.pref +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/labs.pref @@ -9,3 +9,12 @@ Labs: - the advanced cataloging editor. - "
NOTE:" - This feature is currently experimental, and may have bugs that cause corruption of records. It also does not include any support for UNIMARC or NORMARC fixed fields. Please help us test it and report any bugs, but do so at your own risk. + - + - pref: TemplateToolkitNotices + default: 0 + choices: + yes: Enable + no: "Don't enable" + - the ability to use Template Toolkit syntax in slips and notices. + - "
NOTE:" + - This feature is currently experimental, the specific variables available may be subject to change. --- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/letter.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/letter.tt @@ -394,12 +394,25 @@ $(document).ready(function() {
  1. + [% IF letter.is_html %] [% ELSE %] [% END %] + + [% IF Koha.Preference('TemplateToolkitNotices') %] +
    + + + [% IF letter.is_tt %] + + [% ELSE %] + + [% END %] + Enables the use of the new experimental Template Toolkit syntax parser instead of the current syntax parser. + [% END %]
  2. --- a/t/db_dependent/Letters/TemplateToolkit.t +++ a/t/db_dependent/Letters/TemplateToolkit.t @@ -92,7 +92,7 @@ my $modification = Koha::Borrower::Modification->new( { verification_token => "T my $prepared_letter; my $sth = - $dbh->prepare(q{INSERT INTO letter (module, code, name, title, content) VALUES ('test',?,'Test','Test',?)}); + $dbh->prepare(q{INSERT INTO letter (module, code, name, title, is_tt, content) VALUES ('test',?,'Test','Test',1,?)}); $sth->execute( "TEST_PATRON", "[% borrower.id %]" ); $prepared_letter = GetPreparedLetter( --- a/tools/letter.pl +++ a/tools/letter.pl @@ -170,6 +170,7 @@ sub add_form { push @letter_loop, { message_transport_type => $mtt, is_html => $letters->{$mtt}{is_html}, + is_tt => $letters->{$mtt}{is_tt}, title => $letters->{$mtt}{title}, content => $letters->{$mtt}{content}//'', }; @@ -259,6 +260,7 @@ sub add_validate { my @content = $input->param('content'); for my $mtt ( @mtt ) { my $is_html = $input->param("is_html_$mtt"); + my $is_tt = $input->param("is_tt_$mtt"); my $title = shift @title; my $content = shift @content; my $letter = C4::Letters::getletter( $oldmodule, $code, $branchcode, $mtt); @@ -277,18 +279,18 @@ sub add_validate { $dbh->do( q{ UPDATE letter - SET branchcode = ?, module = ?, name = ?, is_html = ?, title = ?, content = ? + SET branchcode = ?, module = ?, name = ?, is_html = ?, title = ?, content = ?, is_tt = ? WHERE branchcode = ? AND module = ? AND code = ? AND message_transport_type = ? }, undef, - $branchcode || '', $module, $name, $is_html || 0, $title, $content, + $branchcode || '', $module, $name, $is_html || 0, $title, $content, $is_tt, $branchcode, $oldmodule, $code, $mtt ); } else { $dbh->do( - q{INSERT INTO letter (branchcode,module,code,name,is_html,title,content,message_transport_type) VALUES (?,?,?,?,?,?,?,?)}, + q{INSERT INTO letter (branchcode,module,code,name,is_html,title,content,message_transport_type,is_tt) VALUES (?,?,?,?,?,?,?,?,?)}, undef, - $branchcode || '', $module, $code, $name, $is_html || 0, $title, $content, $mtt + $branchcode || '', $module, $code, $name, $is_html || 0, $title, $content, $mtt, $is_tt ); } } --