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

(-)a/Koha/XSLT_Handler.pm (-66 / +39 lines)
Lines 28-35 Koha::XSLT_Handler - Facilitate use of XSLT transformations Link Here
28
    my $output = $xslt_engine->transform($xml, $xsltfilename);
28
    my $output = $xslt_engine->transform($xml, $xsltfilename);
29
    $output = $xslt_engine->transform({ xml => $xml, file => $file });
29
    $output = $xslt_engine->transform({ xml => $xml, file => $file });
30
    $output = $xslt_engine->transform({ xml => $xml, code => $code });
30
    $output = $xslt_engine->transform({ xml => $xml, code => $code });
31
    my $err= $xslt_engine->err; # error number
31
    my $err= $xslt_engine->err; # error code
32
    my $errstr= $xslt_engine->errstr; # error message
33
    $xslt_engine->refresh($xsltfilename);
32
    $xslt_engine->refresh($xsltfilename);
34
33
35
=head1 DESCRIPTION
34
=head1 DESCRIPTION
Lines 37-43 Koha::XSLT_Handler - Facilitate use of XSLT transformations Link Here
37
    A XSLT handler object on top of LibXML and LibXSLT, allowing you to
36
    A XSLT handler object on top of LibXML and LibXSLT, allowing you to
38
    run XSLT stylesheets repeatedly without loading them again.
37
    run XSLT stylesheets repeatedly without loading them again.
39
    Errors occurring during loading, parsing or transforming are reported
38
    Errors occurring during loading, parsing or transforming are reported
40
    via the err and errstr attributes.
39
    via the err attribute.
41
    Reloading XSLT files can be done with the refresh method.
40
    Reloading XSLT files can be done with the refresh method.
42
41
43
=head1 METHODS
42
=head1 METHODS
Lines 58-68 Koha::XSLT_Handler - Facilitate use of XSLT transformations Link Here
58
57
59
=head2 err
58
=head2 err
60
59
61
    Error number (see list of ERROR CODES)
60
    Error code (see list of ERROR CODES)
62
63
=head2 errstr
64
65
    Error message
66
61
67
=head2 do_not_return_source
62
=head2 do_not_return_source
68
63
Lines 71-105 Koha::XSLT_Handler - Facilitate use of XSLT transformations Link Here
71
66
72
=head2 print_warns
67
=head2 print_warns
73
68
74
    If set, print error messages to STDERR. True by default.
69
    If set, print error messages to STDERR. False by default. Looks at the
70
    DEBUG environment variable too.
75
71
76
=head1 ERROR CODES
72
=head1 ERROR CODES
77
73
78
=head2 Error 1
74
=head2 Error XSLTH_ERR_NO_FILE
79
75
80
    No XSLT file passed
76
    No XSLT file passed
81
77
82
=head2 Error 2
78
=head2 Error XSLTH_ERR_FILE_NOT_FOUND
83
79
84
    XSLT file not found
80
    XSLT file not found
85
81
86
=head2 Error 3
82
=head2 Error XSLTH_ERR_LOADING
87
83
88
    Error while loading stylesheet xml: [furter information]
84
    Error while loading stylesheet xml: [optional warnings]
89
85
90
=head2 Error 4
86
=head2 Error XSLTH_ERR_PARSING_CODE
91
87
92
    Error while parsing stylesheet: [furter information]
88
    Error while parsing stylesheet: [optional warnings]
93
89
94
=head2 Error 5
90
=head2 Error XSLTH_ERR_PARSING_DATA
95
91
96
    Error while parsing input: [furter information]
92
    Error while parsing input: [optional warnings]
97
93
98
=head2 Error 6
94
=head2 Error XSLTH_ERR_TRANSFORMING
99
95
100
    Error while transforming input: [furter information]
96
    Error while transforming input: [optional warnings]
101
97
102
=head2 Error 7
98
=head2 Error XSLTH_NO_STRING_PASSED
103
99
104
    No string to transform
100
    No string to transform
105
101
Lines 125-133 use XML::LibXSLT; Link Here
125
121
126
use base qw(Class::Accessor);
122
use base qw(Class::Accessor);
127
123
128
__PACKAGE__->mk_ro_accessors(qw( err errstr ));
124
__PACKAGE__->mk_ro_accessors(qw( err ));
129
__PACKAGE__->mk_accessors(qw( do_not_return_source print_warns ));
125
__PACKAGE__->mk_accessors(qw( do_not_return_source print_warns ));
130
126
127
use constant XSLTH_ERR_1    => 'XSLTH_ERR_NO_FILE';
128
use constant XSLTH_ERR_2    => 'XSLTH_ERR_FILE_NOT_FOUND';
129
use constant XSLTH_ERR_3    => 'XSLTH_ERR_LOADING';
130
use constant XSLTH_ERR_4    => 'XSLTH_ERR_PARSING_CODE';
131
use constant XSLTH_ERR_5    => 'XSLTH_ERR_PARSING_DATA';
132
use constant XSLTH_ERR_6    => 'XSLTH_ERR_TRANSFORMING';
133
use constant XSLTH_ERR_7    => 'XSLTH_NO_STRING_PASSED';
134
131
=head2 transform
135
=head2 transform
132
136
133
    my $output= $xslt_engine->transform( $xml, $xsltfilename, [$format] );
137
    my $output= $xslt_engine->transform( $xml, $xsltfilename, [$format] );
Lines 180-186 sub transform { Link Here
180
184
181
    #check if no string passed
185
    #check if no string passed
182
    if ( !defined $xml ) {
186
    if ( !defined $xml ) {
183
        $self->_set_error(7);
187
        $self->_set_error( XSLTH_ERR_7 );
184
        return;               #always undef
188
        return;               #always undef
185
    }
189
    }
186
190
Lines 193-199 sub transform { Link Here
193
    my $parser = XML::LibXML->new();
197
    my $parser = XML::LibXML->new();
194
    my $source = eval { $parser->parse_string($xml) };
198
    my $source = eval { $parser->parse_string($xml) };
195
    if ($@) {
199
    if ($@) {
196
        $self->_set_error( 5, $@ );
200
        $self->_set_error( XSLTH_ERR_5, $@ );
197
        return $retval;
201
        return $retval;
198
    }
202
    }
199
    my $result = eval {
203
    my $result = eval {
Lines 213-219 sub transform { Link Here
213
            : $stsh->output_as_chars( $transformed ); # default: chars
217
            : $stsh->output_as_chars( $transformed ); # default: chars
214
    };
218
    };
215
    if ($@) {
219
    if ($@) {
216
        $self->_set_error( 6, $@ );
220
        $self->_set_error( XSLTH_ERR_6, $@ );
217
        return $retval;
221
        return $retval;
218
    }
222
    }
219
    $self->{last_xsltfile} = $key;
223
    $self->{last_xsltfile} = $key;
Lines 259-266 sub _init { Link Here
259
    my $self = shift;
263
    my $self = shift;
260
264
261
    $self->_set_error;
265
    $self->_set_error;
262
    $self->{xslt_hash}            = {};
266
    $self->{xslt_hash} = {};
263
    $self->{print_warns}          = 1 unless exists $self->{print_warns};
267
    $self->{print_warns} = exists $self->{print_warns}
268
        ? $self->{print_warns}
269
        : $ENV{DEBUG} // 0;
264
    $self->{do_not_return_source} = 0
270
    $self->{do_not_return_source} = 0
265
      unless exists $self->{do_not_return_source};
271
      unless exists $self->{do_not_return_source};
266
272
Lines 281-287 sub _load { Link Here
281
    if ( !$filename && !$code ) {
287
    if ( !$filename && !$code ) {
282
        my $last = $self->{last_xsltfile};
288
        my $last = $self->{last_xsltfile};
283
        if ( !$last || !exists $self->{xslt_hash}->{$last} ) {
289
        if ( !$last || !exists $self->{xslt_hash}->{$last} ) {
284
            $self->_set_error(1);
290
            $self->_set_error( XSLTH_ERR_1 );
285
            return;
291
            return;
286
        }
292
        }
287
        return $last;
293
        return $last;
Lines 300-306 sub _load { Link Here
300
306
301
    #Check file existence (skipping URLs)
307
    #Check file existence (skipping URLs)
302
    if( $filename && $filename !~ /^https?:\/\// && !-e $filename ) {
308
    if( $filename && $filename !~ /^https?:\/\// && !-e $filename ) {
303
        $self->_set_error(2);
309
        $self->_set_error( XSLTH_ERR_2 );
304
        return;
310
        return;
305
    }
311
    }
306
312
Lines 310-316 sub _load { Link Here
310
        $parser->load_xml( $self->_load_xml_args($filename, $code) )
316
        $parser->load_xml( $self->_load_xml_args($filename, $code) )
311
    };
317
    };
312
    if ($@) {
318
    if ($@) {
313
        $self->_set_error( 3, $@ );
319
        $self->_set_error( XSLTH_ERR_3, $@ );
314
        return;
320
        return;
315
    }
321
    }
316
322
Lines 319-325 sub _load { Link Here
319
    $rv = $code? $digest.$codelen: $filename;
325
    $rv = $code? $digest.$codelen: $filename;
320
    $self->{xslt_hash}->{$rv} = eval { $xslt->parse_stylesheet($style_doc) };
326
    $self->{xslt_hash}->{$rv} = eval { $xslt->parse_stylesheet($style_doc) };
321
    if ($@) {
327
    if ($@) {
322
        $self->_set_error( 4, $@ );
328
        $self->_set_error( XSLTH_ERR_4, $@ );
323
        delete $self->{xslt_hash}->{$rv};
329
        delete $self->{xslt_hash}->{$rv};
324
        return;
330
        return;
325
    }
331
    }
Lines 335-377 sub _load_xml_args { Link Here
335
# Internal routine for handling error information.
341
# Internal routine for handling error information.
336
342
337
sub _set_error {
343
sub _set_error {
338
    my ( $self, $errno, $addmsg ) = @_;
344
    my ( $self, $errcode, $warn ) = @_;
339
345
340
    if ( !$errno ) {    #clear the error
346
    $self->{err} = $errcode; #set or clear error
341
        $self->{err}    = undef;
347
    warn 'XSLT_Handler: '. $warn if $warn && $self->{print_warns};
342
        $self->{errstr} = undef;
343
        return;
344
    }
345
346
    $self->{err} = $errno;
347
    if ( $errno == 1 ) {
348
        $self->{errstr} = "No XSLT file passed.";
349
    }
350
    elsif ( $errno == 2 ) {
351
        $self->{errstr} = "XSLT file not found.";
352
    }
353
    elsif ( $errno == 3 ) {
354
        $self->{errstr} = "Error while loading stylesheet xml:";
355
    }
356
    elsif ( $errno == 4 ) {
357
        $self->{errstr} = "Error while parsing stylesheet:";
358
    }
359
    elsif ( $errno == 5 ) {
360
        $self->{errstr} = "Error while parsing input:";
361
    }
362
    elsif ( $errno == 6 ) {
363
        $self->{errstr} = "Error while transforming input:";
364
    }
365
    elsif ( $errno == 7 ) {
366
        $self->{errstr} = "No string to transform.";
367
    }
368
369
    if ($addmsg) {
370
        $self->{errstr} .= " $addmsg";
371
    }
372
373
    warn $self->{errstr} if $self->{print_warns};
374
    return;
375
}
348
}
376
349
377
=head1 AUTHOR
350
=head1 AUTHOR
(-)a/t/db_dependent/XSLT_Handler.t (-35 / +26 lines)
Lines 21-27 use Modern::Perl; Link Here
21
21
22
use FindBin;
22
use FindBin;
23
use File::Slurp;
23
use File::Slurp;
24
use Test::More tests => 41;
24
use Test::More tests => 35;
25
use Test::Warn;
25
use Test::Warn;
26
26
27
use Koha::XSLT_Handler;
27
use Koha::XSLT_Handler;
Lines 29-43 use Koha::XSLT_Handler; Link Here
29
my $engine=Koha::XSLT_Handler->new;
29
my $engine=Koha::XSLT_Handler->new;
30
is( ref $engine, 'Koha::XSLT_Handler', 'Testing creation of handler object' );
30
is( ref $engine, 'Koha::XSLT_Handler', 'Testing creation of handler object' );
31
31
32
warning_is { $engine->transform('') } #we passed no file at first time
32
$engine->transform('');
33
            "No XSLT file passed.",
33
is( $engine->err, Koha::XSLT_Handler::XSLTH_ERR_1, 'Engine returns error on no file' );
34
            "No XSLT warning correctly displayed";
35
is( $engine->err, 1, 'Engine returns error on no file' );
36
34
37
warning_is { $engine->transform( '', 'thisfileshouldnotexist.%$#@' ) }
35
$engine->transform( '', 'thisfileshouldnotexist.%$#@' );
38
            "XSLT file not found.",
36
is( $engine->err, Koha::XSLT_Handler::XSLTH_ERR_2, 'Engine returns error on bad file' );
39
            "No XSLT warning correctly displayed";
40
is( $engine->err, 2, 'Engine returns error on bad file' );
41
is( $engine->refresh( 'asdjhaskjh'), 0, 'Test on invalid refresh' );
37
is( $engine->refresh( 'asdjhaskjh'), 0, 'Test on invalid refresh' );
42
38
43
#check first test xsl
39
#check first test xsl
Lines 51-78 $xsltfile_1= $path.$xsltfile_1; Link Here
51
my $output;
47
my $output;
52
48
53
# Undefined text tests
49
# Undefined text tests
54
warning_is { $output = $engine->transform( undef, $xsltfile_1 ) }
50
$output = $engine->transform( undef, $xsltfile_1 );
55
           "No string to transform.",
51
is( $engine->err, Koha::XSLT_Handler::XSLTH_ERR_7, 'Engine returns error on undefined text' );
56
           "No string warning correctly displayed";
57
is( $engine->err, 7, 'Engine returns error on undefined text' );
58
52
59
# Empty string tests
53
# Empty string tests
60
warning_is { $output = $engine->transform( '', $xsltfile_1 ) }
54
$output = $engine->transform( '', $xsltfile_1 );
61
           "Error while parsing input: Empty String",
55
is( $engine->err, Koha::XSLT_Handler::XSLTH_ERR_5, 'Engine returns error on empty string' );
62
           "Empty string warning correctly displayed";
63
is( $engine->err, 5, 'Engine returns error on empty string' );
64
56
65
# Non-XML tests
57
# Non-XML tests
58
$engine->print_warns(1);
66
warning_like { $output = $engine->transform( 'abcdef', $xsltfile_1 ) }
59
warning_like { $output = $engine->transform( 'abcdef', $xsltfile_1 ) }
67
           qr{^Error while parsing input: :1: parser error : Start tag expected, '<' not found},
60
    qr{parser error : Start tag expected, '<' not found},
68
           "Non-XML warning correctly displayed";
61
    "Non-XML warning correctly displayed";
69
is( $engine->err, 5, 'Engine returns error on non-xml' );
62
is( $engine->err, Koha::XSLT_Handler::XSLTH_ERR_5, 'Engine returns error on non-xml' );
70
63
71
# Malformed XML tests
64
# Malformed XML tests
72
warning_like { $output = $engine->transform( '<a></b>', $xsltfile_1 ) }
65
warning_like { $output = $engine->transform( '<a></b>', $xsltfile_1 ) }
73
             qr{^Error while parsing input: :1: parser error : Opening and ending tag mismatch: a line 1 and b},
66
    qr{parser error : Opening and ending tag mismatch: a line 1 and b},
74
             "Malformed XML warning correctly displayed";
67
    "Malformed XML warning correctly displayed";
75
is( $engine->err, 5, 'Engine returns error on malformed xml' );
68
is( $engine->err, Koha::XSLT_Handler::XSLTH_ERR_5, 'Engine returns error on malformed xml' );
76
69
77
#Test not returning source on failure when asked for
70
#Test not returning source on failure when asked for
78
#Include passing do_not_return via constructor on second engine
71
#Include passing do_not_return via constructor on second engine
Lines 82-99 my $secondengine=Koha::XSLT_Handler->new( { Link Here
82
});
75
});
83
$engine->do_not_return_source(1);
76
$engine->do_not_return_source(1);
84
warning_like { $output = $engine->transform( '<a></b>', $xsltfile_1 ) }
77
warning_like { $output = $engine->transform( '<a></b>', $xsltfile_1 ) }
85
             qr{^Error while parsing input: :1: parser error : Opening and ending tag mismatch: a line 1 and b},
78
    qr{parser error : Opening and ending tag mismatch: a line 1 and b},
86
             "Malformed XML warning correctly displayed";
79
    "Malformed XML warning correctly displayed";
87
is( defined $output? 1: 0, 0, 'Engine respects do_not_return_source==1');
80
is( defined $output? 1: 0, 0, 'Engine respects do_not_return_source==1');
81
$secondengine->print_warns(1);
88
warning_like { $output = $secondengine->transform( '<a></b>', $xsltfile_1 ) }
82
warning_like { $output = $secondengine->transform( '<a></b>', $xsltfile_1 ) }
89
             qr{^Error while parsing input: :1: parser error : Opening and ending tag mismatch: a line 1 and b},
83
    qr{parser error : Opening and ending tag mismatch: a line 1 and b},
90
             "Malformed XML warning correctly displayed";
84
    "Malformed XML warning correctly displayed";
91
is( defined $output? 1: 0, 0, 'Second engine respects it too');
85
is( defined $output? 1: 0, 0, 'Second engine respects it too');
92
undef $secondengine; #bye
86
undef $secondengine; #bye
93
$engine->do_not_return_source(0);
87
$engine->do_not_return_source(0);
94
warning_like { $output = $engine->transform( '<a></b>', $xsltfile_1 ) }
88
warning_like { $output = $engine->transform( '<a></b>', $xsltfile_1 ) }
95
             qr{^Error while parsing input: :1: parser error : Opening and ending tag mismatch: a line 1 and b},
89
    qr{parser error : Opening and ending tag mismatch: a line 1 and b},
96
             "Malformed XML warning correctly displayed";
90
    "Malformed XML warning correctly displayed";
97
is( defined $output? 1: 0, 1, 'Engine respects do_not_return_source==0');
91
is( defined $output? 1: 0, 1, 'Engine respects do_not_return_source==0');
98
92
99
#Testing valid refresh now
93
#Testing valid refresh now
Lines 146-156 is( -e $path.$xsltfile_2, 1, "Found my test stylesheet $xsltfile_2" ); Link Here
146
exit if !-e $path.$xsltfile_2;
140
exit if !-e $path.$xsltfile_2;
147
$xsltfile_2= $path.$xsltfile_2;
141
$xsltfile_2= $path.$xsltfile_2;
148
142
149
warning_like { $output = $engine->transform( $xml_2, $xsltfile_2 ) }
143
$engine->print_warns(0);
150
             qr{^Error while parsing stylesheet:},
144
$output = $engine->transform( $xml_2, $xsltfile_2 );
151
             "Bad XSL warning correctly displayed";
145
is( $engine->err, Koha::XSLT_Handler::XSLTH_ERR_4, 'Engine returned error for parsing bad xsl' );
152
is( $engine->err, 4, 'Engine returned error for parsing bad xsl' );
153
is( defined($engine->errstr), 1, 'Error string contains text');
154
146
155
#The third test xsl is okay again; main use is clearing two items from cache
147
#The third test xsl is okay again; main use is clearing two items from cache
156
my $xsltfile_3 = 'test03.xsl';
148
my $xsltfile_3 = 'test03.xsl';
157
- 

Return to bug 20272