View | Details | Raw Unified | Return to bug 14757
Collapse All | Expand All

(-)a/C4/Letters.pm (-68 / +83 lines)
Lines 124-130 sub GetLetterTemplates { Link Here
124
    my $dbh       = C4::Context->dbh;
124
    my $dbh       = C4::Context->dbh;
125
    my $letters   = $dbh->selectall_hashref(
125
    my $letters   = $dbh->selectall_hashref(
126
        q|
126
        q|
127
            SELECT module, code, branchcode, name, is_html, title, content, message_transport_type
127
            SELECT module, code, branchcode, name, is_html, title, content, message_transport_type, is_tt
128
            FROM letter
128
            FROM letter
129
            WHERE module = ?
129
            WHERE module = ?
130
            AND code = ?
130
            AND code = ?
Lines 642-730 sub GetPreparedLetter { Link Here
642
        or warn( "No $module $letter_code letter transported by " . $mtt ),
642
        or warn( "No $module $letter_code letter transported by " . $mtt ),
643
            return;
643
            return;
644
644
645
    my $tables = $params{tables};
645
    my $tables     = $params{tables};
646
    my $substitute = $params{substitute};
646
    my $substitute = $params{substitute};
647
    my $repeat = $params{repeat};
647
    my $repeat     = $params{repeat};
648
648
    $tables || $substitute || $repeat
649
    $tables || $substitute || $repeat
649
      or carp( "ERROR: nothing to substitute - both 'tables' and 'substitute' are empty" ),
650
      or carp( "ERROR: nothing to substitute - both 'tables' and 'substitute' are empty" ),
650
         return;
651
         return;
651
    my $want_librarian = $params{want_librarian};
652
652
653
    if ($substitute) {
653
    my $userenv = C4::Context->userenv;
654
        while ( my ($token, $val) = each %$substitute ) {
655
            if ( $token eq 'items.content' ) {
656
                $val =~ s|\n|<br/>|g if $letter->{is_html};
657
            }
658
654
659
            $letter->{title} =~ s/<<$token>>/$val/g;
655
    if ( $letter->{is_tt} ) {
660
            $letter->{content} =~ s/<<$token>>/$val/g;
656
        $letter->{content} = _process_tt(
661
       }
657
            {
658
                content => $letter->{content},
659
                tables  => $tables,
660
                tt_params  => {
661
                    today     => dt_from_string(),
662
                    librarian => {
663
                        firstname    => $userenv->{firstname},
664
                        surname      => $userenv->{surname},
665
                        emailaddress => $userenv->{emailaddress},
666
                    },
667
                }
668
            }
669
        );
662
    }
670
    }
671
    else {
672
        my $want_librarian = $params{want_librarian};
663
673
664
    my $OPACBaseURL = C4::Context->preference('OPACBaseURL');
674
        if ($substitute) {
665
    $letter->{content} =~ s/<<OPACBaseURL>>/$OPACBaseURL/go;
675
            while ( my ($token, $val) = each %$substitute ) {
676
                if ( $token eq 'items.content' ) {
677
                    $val =~ s|\n|<br/>|g if $letter->{is_html};
678
                }
666
679
667
    if ($want_librarian) {
680
                $letter->{title} =~ s/<<$token>>/$val/g;
668
        # parsing librarian name
681
                $letter->{content} =~ s/<<$token>>/$val/g;
669
        my $userenv = C4::Context->userenv;
682
           }
670
        $letter->{content} =~ s/<<LibrarianFirstname>>/$userenv->{firstname}/go;
683
        }
671
        $letter->{content} =~ s/<<LibrarianSurname>>/$userenv->{surname}/go;
672
        $letter->{content} =~ s/<<LibrarianEmailaddress>>/$userenv->{emailaddress}/go;
673
    }
674
684
675
    my ($repeat_no_enclosing_tags, $repeat_enclosing_tags);
685
        my $OPACBaseURL = C4::Context->preference('OPACBaseURL');
686
        $letter->{content} =~ s/<<OPACBaseURL>>/$OPACBaseURL/go;
676
687
677
    if ($repeat) {
688
        if ($want_librarian) {
678
        if (ref ($repeat) eq 'ARRAY' ) {
689
            # parsing librarian name
679
            $repeat_no_enclosing_tags = $repeat;
690
            $letter->{content} =~ s/<<LibrarianFirstname>>/$userenv->{firstname}/go;
680
        } else {
691
            $letter->{content} =~ s/<<LibrarianSurname>>/$userenv->{surname}/go;
681
            $repeat_enclosing_tags = $repeat;
692
            $letter->{content} =~ s/<<LibrarianEmailaddress>>/$userenv->{emailaddress}/go;
682
        }
693
        }
683
    }
684
694
685
    if ($repeat_enclosing_tags) {
695
        my ($repeat_no_enclosing_tags, $repeat_enclosing_tags);
686
        while ( my ($tag, $tag_tables) = each %$repeat_enclosing_tags ) {
696
687
            if ( $letter->{content} =~ m!<$tag>(.*)</$tag>!s ) {
697
        if ($repeat) {
688
                my $subcontent = $1;
698
            if (ref ($repeat) eq 'ARRAY' ) {
689
                my @lines = map {
699
                $repeat_no_enclosing_tags = $repeat;
690
                    my %subletter = ( title => '', content => $subcontent );
700
            } else {
691
                    _substitute_tables( \%subletter, $_ );
701
                $repeat_enclosing_tags = $repeat;
692
                    $subletter{content};
693
                } @$tag_tables;
694
                $letter->{content} =~ s!<$tag>.*</$tag>!join( "\n", @lines )!se;
695
            }
702
            }
696
        }
703
        }
697
    }
698
699
    if ($tables) {
700
        _substitute_tables( $letter, $tables );
701
    }
702
704
703
    if ($repeat_no_enclosing_tags) {
705
        if ($repeat_enclosing_tags) {
704
        if ( $letter->{content} =~ m/[^\n]*<<.*>>[^\n]*/so ) {
706
            while ( my ($tag, $tag_tables) = each %$repeat_enclosing_tags ) {
705
            my $line = $&;
707
                if ( $letter->{content} =~ m!<$tag>(.*)</$tag>!s ) {
706
            my $i = 1;
708
                    my $subcontent = $1;
707
            my @lines = map {
709
                    my @lines = map {
708
                my $c = $line;
710
                        my %subletter = ( title => '', content => $subcontent );
709
                $c =~ s/<<count>>/$i/go;
711
                        _substitute_tables( \%subletter, $_ );
710
                foreach my $field ( keys %{$_} ) {
712
                        $subletter{content};
711
                    $c =~ s/(<<[^\.]+.$field>>)/$_->{$field}/;
713
                    } @$tag_tables;
714
                    $letter->{content} =~ s!<$tag>.*</$tag>!join( "\n", @lines )!se;
712
                }
715
                }
713
                $i++;
716
            }
714
                $c;
717
        }
715
            } @$repeat_no_enclosing_tags;
716
718
717
            my $replaceby = join( "\n", @lines );
719
        if ($tables) {
718
            $letter->{content} =~ s/\Q$line\E/$replaceby/s;
720
            _substitute_tables( $letter, $tables );
719
        }
721
        }
720
    }
721
722
722
    $letter->{content} = _process_tt(
723
        if ($repeat_no_enclosing_tags) {
723
        {
724
            if ( $letter->{content} =~ m/[^\n]*<<.*>>[^\n]*/so ) {
724
            content => $letter->{content},
725
                my $line = $&;
725
            tables  => $tables,
726
                my $i = 1;
727
                my @lines = map {
728
                    my $c = $line;
729
                    $c =~ s/<<count>>/$i/go;
730
                    foreach my $field ( keys %{$_} ) {
731
                        $c =~ s/(<<[^\.]+.$field>>)/$_->{$field}/;
732
                    }
733
                    $i++;
734
                    $c;
735
                } @$repeat_no_enclosing_tags;
736
737
                my $replaceby = join( "\n", @lines );
738
                $letter->{content} =~ s/\Q$line\E/$replaceby/s;
739
            }
726
        }
740
        }
727
    );
741
742
    }
728
743
729
    $letter->{content} =~ s/<<\S*>>//go; #remove any stragglers
744
    $letter->{content} =~ s/<<\S*>>//go; #remove any stragglers
730
745
Lines 1387-1394 sub _set_message_status { Link Here
1387
sub _process_tt {
1402
sub _process_tt {
1388
    my ( $params ) = @_;
1403
    my ( $params ) = @_;
1389
1404
1390
    my $content = $params->{content};
1405
    my $content   = $params->{content};
1391
    my $tables = $params->{tables};
1406
    my $tables    = $params->{tables};
1407
    my $tt_params = $params->{tt_params};
1392
1408
1393
    my $use_template_cache = C4::Context->config('template_cache_dir') && defined $ENV{GATEWAY_INTERFACE};
1409
    my $use_template_cache = C4::Context->config('template_cache_dir') && defined $ENV{GATEWAY_INTERFACE};
1394
    my $template           = Template->new(
1410
    my $template           = Template->new(
Lines 1403-1409 sub _process_tt { Link Here
1403
        }
1419
        }
1404
    ) or die Template->error();
1420
    ) or die Template->error();
1405
1421
1406
    my $tt_params = _get_tt_params( $tables );
1422
    my $tt_objects = _get_tt_params( $tables );
1423
    $tt_params = { %$tt_params, %$tt_objects };
1407
1424
1408
    my $output;
1425
    my $output;
1409
    $template->process( \$content, $tt_params, \$output ) || croak "ERROR PROCESSING TEMPLATE: " . $template->error();
1426
    $template->process( \$content, $tt_params, \$output ) || croak "ERROR PROCESSING TEMPLATE: " . $template->error();
Lines 1524-1531 sub _get_tt_params { Link Here
1524
        }
1541
        }
1525
    }
1542
    }
1526
1543
1527
    $params->{today} = dt_from_string();
1528
1529
    return $params;
1544
    return $params;
1530
}
1545
}
1531
1546
(-)a/installer/data/mysql/atomicupdate/bug_14757.sql (+4 lines)
Line 0 Link Here
1
ALTER TABLE letter ADD is_tt TINYINT(1) NOT NULL DEFAULT 0 AFTER message_transport_type;
2
3
INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, `type` ) VALUES
4
('TemplateToolkitNotices',0,'','Enable the ability to use Template Toolkit syntax in slips and notices','YesNo');
(-)a/installer/data/mysql/kohastructure.sql (+1 lines)
Lines 1430-1435 CREATE TABLE `letter` ( -- table for all notice templates in Koha Link Here
1430
  `title` varchar(200) NOT NULL default '', -- subject line of the notice
1430
  `title` varchar(200) NOT NULL default '', -- subject line of the notice
1431
  `content` text, -- body text for the notice or slip
1431
  `content` text, -- body text for the notice or slip
1432
  `message_transport_type` varchar(20) NOT NULL DEFAULT 'email', -- transport type for this notice
1432
  `message_transport_type` varchar(20) NOT NULL DEFAULT 'email', -- transport type for this notice
1433
  `is_tt` TINYINT(1) NOT NULL DEFAULT 0, -- controls if notice should be processed as template toolkit syntax
1433
  PRIMARY KEY  (`module`,`code`, `branchcode`, `message_transport_type`),
1434
  PRIMARY KEY  (`module`,`code`, `branchcode`, `message_transport_type`),
1434
  CONSTRAINT `message_transport_type_fk` FOREIGN KEY (`message_transport_type`)
1435
  CONSTRAINT `message_transport_type_fk` FOREIGN KEY (`message_transport_type`)
1435
  REFERENCES `message_transport_types` (`message_transport_type`) ON DELETE CASCADE ON UPDATE CASCADE
1436
  REFERENCES `message_transport_types` (`message_transport_type`) ON DELETE CASCADE ON UPDATE CASCADE
(-)a/installer/data/mysql/sysprefs.sql (+1 lines)
Lines 476-481 INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` Link Here
476
('TagsModeration','0','','Require tags from patrons to be approved before becoming visible.','YesNo'),
476
('TagsModeration','0','','Require tags from patrons to be approved before becoming visible.','YesNo'),
477
('TagsShowOnDetail','10','','Number of tags to display on detail page.  0 is off.','Integer'),
477
('TagsShowOnDetail','10','','Number of tags to display on detail page.  0 is off.','Integer'),
478
('TagsShowOnList','6','','Number of tags to display on search results list.  0 is off.','Integer'),
478
('TagsShowOnList','6','','Number of tags to display on search results list.  0 is off.','Integer'),
479
('TemplateToolkitNotices',0,'','Enable the ability to use Template Toolkit syntax in slips and notices','YesNo'),
479
('template','prog','','Define the preferred staff interface template','Themes'),
480
('template','prog','','Define the preferred staff interface template','Themes'),
480
('ThingISBN','0','','Use with FRBRizeEditions. If ON, Koha will use the ThingISBN web service in the Editions tab on the detail pages.','YesNo'),
481
('ThingISBN','0','','Use with FRBRizeEditions. If ON, Koha will use the ThingISBN web service in the Editions tab on the detail pages.','YesNo'),
481
('TimeFormat','24hr','12hr|24hr','Defines the global time format for visual output.','Choice'),
482
('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 (+9 lines)
Lines 9-11 Labs: Link Here
9
            - the advanced cataloging editor.
9
            - the advanced cataloging editor.
10
            - "<br/> NOTE:"
10
            - "<br/> NOTE:"
11
            - 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.
11
            - 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.
12
        -
13
            - pref: TemplateToolkitNotices
14
              default: 0
15
              choices:
16
                  yes: Enable
17
                  no: "Don't enable"
18
            - the ability to use Template Toolkit syntax in slips and notices.
19
            - "<br/> NOTE:"
20
            - 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 (+13 lines)
Lines 394-405 $(document).ready(function() { Link Here
394
              <ol>
394
              <ol>
395
                <li>
395
                <li>
396
                  <input type="hidden" name="message_transport_type" value="[% letter.message_transport_type %]" />
396
                  <input type="hidden" name="message_transport_type" value="[% letter.message_transport_type %]" />
397
397
                  <label for="is_html_[% letter.message_transport_type %]">HTML message:</label>
398
                  <label for="is_html_[% letter.message_transport_type %]">HTML message:</label>
398
                  [% IF letter.is_html %]
399
                  [% IF letter.is_html %]
399
                    <input type="checkbox" name="is_html_[% letter.message_transport_type %]" id="is_html_[% letter.message_transport_type %]" value="1" checked="checked" />
400
                    <input type="checkbox" name="is_html_[% letter.message_transport_type %]" id="is_html_[% letter.message_transport_type %]" value="1" checked="checked" />
400
                  [% ELSE %]
401
                  [% ELSE %]
401
                    <input type="checkbox" name="is_html_[% letter.message_transport_type %]" id="is_html_[% letter.message_transport_type %]" value="1" />
402
                    <input type="checkbox" name="is_html_[% letter.message_transport_type %]" id="is_html_[% letter.message_transport_type %]" value="1" />
402
                  [% END %]
403
                  [% END %]
404
405
                  [% IF Koha.Preference('TemplateToolkitNotices') %]
406
                      <br />
407
408
                      <label for="is_tt_[% letter.message_transport_type %]">Template Toolkit:</label>
409
                      [% IF letter.is_tt %]
410
                        <input type="checkbox" name="is_tt_[% letter.message_transport_type %]" id="is_tt_[% letter.message_transport_type %]" value="1" checked="checked" />
411
                      [% ELSE %]
412
                        <input type="checkbox" name="is_tt_[% letter.message_transport_type %]" id="is_tt_[% letter.message_transport_type %]" value="1" />
413
                      [% END %]
414
                      <i>Enables the use of the new experimental Template Toolkit syntax parser instead of the current syntax parser.</i>
415
                  [% END %]
403
                </li>
416
                </li>
404
                <li>
417
                <li>
405
                  <label for="title_[% letter.message_transport_type %]">Message subject:</label><input type="text" id="title_[% letter.message_transport_type %]" name="title" size="60" value="[% letter.title %]" />
418
                  <label for="title_[% letter.message_transport_type %]">Message subject:</label><input type="text" id="title_[% letter.message_transport_type %]" name="title" size="60" value="[% letter.title %]" />
(-)a/t/db_dependent/Letters/TemplateToolkit.t (-1 / +1 lines)
Lines 92-98 my $modification = Koha::Borrower::Modification->new( { verification_token => "T Link Here
92
my $prepared_letter;
92
my $prepared_letter;
93
93
94
my $sth =
94
my $sth =
95
  $dbh->prepare(q{INSERT INTO letter (module, code, name, title, content) VALUES ('test',?,'Test','Test',?)});
95
  $dbh->prepare(q{INSERT INTO letter (module, code, name, title, is_tt, content) VALUES ('test',?,'Test','Test',1,?)});
96
96
97
$sth->execute( "TEST_PATRON", "[% borrower.id %]" );
97
$sth->execute( "TEST_PATRON", "[% borrower.id %]" );
98
$prepared_letter = GetPreparedLetter(
98
$prepared_letter = GetPreparedLetter(
(-)a/tools/letter.pl (-5 / +6 lines)
Lines 170-175 sub add_form { Link Here
170
            push @letter_loop, {
170
            push @letter_loop, {
171
                message_transport_type => $mtt,
171
                message_transport_type => $mtt,
172
                is_html    => $letters->{$mtt}{is_html},
172
                is_html    => $letters->{$mtt}{is_html},
173
                is_tt      => $letters->{$mtt}{is_tt},
173
                title      => $letters->{$mtt}{title},
174
                title      => $letters->{$mtt}{title},
174
                content    => $letters->{$mtt}{content}//'',
175
                content    => $letters->{$mtt}{content}//'',
175
            };
176
            };
Lines 259-264 sub add_validate { Link Here
259
    my @content       = $input->param('content');
260
    my @content       = $input->param('content');
260
    for my $mtt ( @mtt ) {
261
    for my $mtt ( @mtt ) {
261
        my $is_html = $input->param("is_html_$mtt");
262
        my $is_html = $input->param("is_html_$mtt");
263
        my $is_tt = $input->param("is_tt_$mtt");
262
        my $title   = shift @title;
264
        my $title   = shift @title;
263
        my $content = shift @content;
265
        my $content = shift @content;
264
        my $letter = C4::Letters::getletter( $oldmodule, $code, $branchcode, $mtt);
266
        my $letter = C4::Letters::getletter( $oldmodule, $code, $branchcode, $mtt);
Lines 277-294 sub add_validate { Link Here
277
            $dbh->do(
279
            $dbh->do(
278
                q{
280
                q{
279
                    UPDATE letter
281
                    UPDATE letter
280
                    SET branchcode = ?, module = ?, name = ?, is_html = ?, title = ?, content = ?
282
                    SET branchcode = ?, module = ?, name = ?, is_html = ?, title = ?, content = ?, is_tt = ?
281
                    WHERE branchcode = ? AND module = ? AND code = ? AND message_transport_type = ?
283
                    WHERE branchcode = ? AND module = ? AND code = ? AND message_transport_type = ?
282
                },
284
                },
283
                undef,
285
                undef,
284
                $branchcode || '', $module, $name, $is_html || 0, $title, $content,
286
                $branchcode || '', $module, $name, $is_html || 0, $title, $content, $is_tt,
285
                $branchcode, $oldmodule, $code, $mtt
287
                $branchcode, $oldmodule, $code, $mtt
286
            );
288
            );
287
        } else {
289
        } else {
288
            $dbh->do(
290
            $dbh->do(
289
                q{INSERT INTO letter (branchcode,module,code,name,is_html,title,content,message_transport_type) VALUES (?,?,?,?,?,?,?,?)},
291
                q{INSERT INTO letter (branchcode,module,code,name,is_html,title,content,message_transport_type,is_tt) VALUES (?,?,?,?,?,?,?,?,?)},
290
                undef,
292
                undef,
291
                $branchcode || '', $module, $code, $name, $is_html || 0, $title, $content, $mtt
293
                $branchcode || '', $module, $code, $name, $is_html || 0, $title, $content, $mtt, $is_tt
292
            );
294
            );
293
        }
295
        }
294
    }
296
    }
295
- 

Return to bug 14757