@@ -, +, @@ descriptions - Addressed all warnings and failures identified by the QA testing tool - Revised the description of the export format (Removed all instances of 'XSL - ') - Updated the description of the custom option in the OpacExportOptions system preference - Corrected the MARC21_simple_export.xsl file to generate a valid HTML file - Introduced the new preference system CustomXSLTExportPath, allowing users to choose the path for the custom XSL files - Updated the sysprefs.sql file for OpacExportOptions and CustomXSLTExportPath - Added a new atomic update file for OpacExportOptions and CustomXSLTExportPath - Updated XSLT tests (t/db_dependent/XSLT.t) - Have more than one record in your catalog ---> There is no 'Simple Export' in the dropdown menu ---> There is now 'Simple Export' option in the dropdown menu ---> a .html file should be downloaded ---> you should see the record informations in the downloaded file ---> a .html file should be downloaded ---> you should see the records informations in the downloaded file ---> a .html file should be downloaded ---> you should see the records informations in the downloaded file ---> Notice that 'Simple Export 1' and 'Simple Export 2' are not in the menu anymore --- C4/XSLT.pm | 298 +++++++++-------- basket/basket.pl | 6 +- basket/downloadcart.pl | 85 ++--- catalogue/detail.pl | 4 +- catalogue/export.pl | 161 +++++---- ...ustomOptionForOpacExportOptions_syspref.pl | 29 ++ installer/data/mysql/mandatory/sysprefs.sql | 3 +- .../prog/en/includes/cat-toolbar.inc | 2 +- .../en/includes/virtualshelves-toolbar.inc | 2 +- .../admin/preferences/cataloguing.pref | 5 + .../en/modules/admin/preferences/opac.pref | 2 +- .../prog/en/modules/basket/basket.tt | 2 +- .../prog/en/modules/catalogue/detail.tt | 2 +- .../modules/virtualshelves/downloadshelf.tt | 2 +- .../biblioexport/MARC21_simple_export.xsl | 131 +++++--- .../en/includes/opac-detail-sidebar.inc | 2 +- .../bootstrap/en/modules/opac-basket.tt | 2 +- .../bootstrap/en/modules/opac-downloadcart.tt | 2 +- .../en/modules/opac-downloadshelf.tt | 2 +- .../bootstrap/en/modules/opac-shelves.tt | 2 +- opac/opac-basket.pl | 91 ++--- opac/opac-detail.pl | 2 +- opac/opac-downloadcart.pl | 97 +++--- opac/opac-downloadshelf.pl | 95 +++--- opac/opac-export.pl | 165 +++++---- opac/opac-shelves.pl | 240 ++++++++------ t/db_dependent/XSLT.t | 313 ++++++++++-------- virtualshelves/downloadshelf.pl | 69 ++-- virtualshelves/shelves.pl | 16 +- 29 files changed, 982 insertions(+), 850 deletions(-) create mode 100755 installer/data/mysql/atomicupdate/bug_17385-CustomOptionForOpacExportOptions_syspref.pl --- a/C4/XSLT.pm +++ a/C4/XSLT.pm @@ -37,19 +37,19 @@ use XML::LibXML; use Encode; use vars qw(@ISA @EXPORT); +my $engine; #XSLT Handler object -my $engine; #XSLT Handler object +our ( @ISA, @EXPORT_OK ); -our (@ISA, @EXPORT_OK); BEGIN { require Exporter; - @ISA = qw(Exporter); + @ISA = qw(Exporter); @EXPORT_OK = qw( buildKohaItemsNamespace XSLTParse4Display &CustomXSLTExportList ); - $engine=Koha::XSLT::Base->new( { do_not_return_source => 1 } ); + $engine = Koha::XSLT::Base->new( { do_not_return_source => 1 } ); } =head1 NAME @@ -71,20 +71,20 @@ The helper function _get_best_default_xslt_filename is used in a unit test. =cut sub _get_best_default_xslt_filename { - my ($htdocs, $theme, $lang, $base_xslfile) = @_; + my ( $htdocs, $theme, $lang, $base_xslfile ) = @_; my @candidates = ( - "$htdocs/$theme/$lang/xslt/${base_xslfile}", # exact match - "$htdocs/$theme/en/xslt/${base_xslfile}", # if not, preferred theme in English - "$htdocs/prog/$lang/xslt/${base_xslfile}", # if not, 'prog' theme in preferred language - "$htdocs/prog/en/xslt/${base_xslfile}", # otherwise, prog theme in English; should always - # exist + "$htdocs/$theme/$lang/xslt/${base_xslfile}", # exact match + "$htdocs/$theme/en/xslt/${base_xslfile}", # if not, preferred theme in English + "$htdocs/prog/$lang/xslt/${base_xslfile}", # if not, 'prog' theme in preferred language + "$htdocs/prog/en/xslt/${base_xslfile}", # otherwise, prog theme in English; should always + # exist ); my $xslfilename; foreach my $filename (@candidates) { $xslfilename = $filename; - if (-f $filename) { - last; # we have a winner! + if ( -f $filename ) { + last; # we have a winner! } } return $xslfilename; @@ -129,65 +129,74 @@ sub get_xslt_sysprefs { return $sysxml; } +=head2 get_xsl_filename + + return xsl filenames in CustomXSLTExportPath or in /koha-tmpl/intranet-tmpl/prog/en/xslt/biblioexport/ + +=cut + sub get_xsl_filename { my ( $xslsyspref, $xslfilename ) = @_; - my $lang = C4::Languages::getlanguage(); + my $lang = C4::Languages::getlanguage(); $xslfilename ||= C4::Context->preference($xslsyspref) || "default"; + my $customXSLTExportPath = C4::Context->preference('CustomXSLTExportPath'); - if ($xslsyspref eq "XSLTCustomExport") { + if ( $xslsyspref eq "XSLTCustomExport" ) { my $dir; - $dir = C4::Context->config('intrahtdocs') . - '/' . C4::Context->preference("template") . - '/' . $lang . - '/xslt/biblioexport'; + $dir = + $customXSLTExportPath ? + $customXSLTExportPath : + C4::Context->config('intrahtdocs') . '/' + . C4::Context->preference("template") . '/' + . $lang + . '/xslt/biblioexport'; $xslfilename = $dir . "/" . $xslfilename; - } elsif ($xslsyspref eq "OPACXSLTCustomExport") { + } elsif ( $xslsyspref eq "OPACXSLTCustomExport" ) { my $dir; - $dir = C4::Context->config('opachtdocs') . - '/' . C4::Context->preference("opacthemes") . - '/' . $lang . - '/xslt/biblioexport'; + $dir = + $customXSLTExportPath ? + $customXSLTExportPath : + C4::Context->config('opachtdocs') . '/' + . C4::Context->preference("opacthemes") . '/' + . $lang + . '/xslt/biblioexport'; $xslfilename = $dir . "/" . $xslfilename; } elsif ( $xslfilename =~ /^\s*"?default"?\s*$/i ) { my ( $htdocs, $theme, $xslfile ); - if ($xslsyspref eq "XSLTDetailsDisplay") { + if ( $xslsyspref eq "XSLTDetailsDisplay" ) { $htdocs = C4::Context->config('intrahtdocs'); $theme = C4::Context->preference("template"); - $xslfile = C4::Context->preference('marcflavour') . - "slim2intranetDetail.xsl"; - } elsif ($xslsyspref eq "XSLTResultsDisplay") { + $xslfile = C4::Context->preference('marcflavour') . "slim2intranetDetail.xsl"; + } elsif ( $xslsyspref eq "XSLTResultsDisplay" ) { $htdocs = C4::Context->config('intrahtdocs'); $theme = C4::Context->preference("template"); - $xslfile = C4::Context->preference('marcflavour') . - "slim2intranetResults.xsl"; - } elsif ($xslsyspref eq "OPACXSLTDetailsDisplay") { + $xslfile = C4::Context->preference('marcflavour') . "slim2intranetResults.xsl"; + } elsif ( $xslsyspref eq "OPACXSLTDetailsDisplay" ) { $htdocs = C4::Context->config('opachtdocs'); $theme = C4::Context->preference("opacthemes"); - $xslfile = C4::Context->preference('marcflavour') . - "slim2OPACDetail.xsl"; - } elsif ($xslsyspref eq "OPACXSLTResultsDisplay") { + $xslfile = C4::Context->preference('marcflavour') . "slim2OPACDetail.xsl"; + } elsif ( $xslsyspref eq "OPACXSLTResultsDisplay" ) { $htdocs = C4::Context->config('opachtdocs'); $theme = C4::Context->preference("opacthemes"); - $xslfile = C4::Context->preference('marcflavour') . - "slim2OPACResults.xsl"; - } elsif ($xslsyspref eq 'XSLTListsDisplay') { + $xslfile = C4::Context->preference('marcflavour') . "slim2OPACResults.xsl"; + } elsif ( $xslsyspref eq 'XSLTListsDisplay' ) { + # Lists default to *Results.xslt $htdocs = C4::Context->config('intrahtdocs'); $theme = C4::Context->preference("template"); - $xslfile = C4::Context->preference('marcflavour') . - "slim2intranetResults.xsl"; - } elsif ($xslsyspref eq 'OPACXSLTListsDisplay') { + $xslfile = C4::Context->preference('marcflavour') . "slim2intranetResults.xsl"; + } elsif ( $xslsyspref eq 'OPACXSLTListsDisplay' ) { + # Lists default to *Results.xslt $htdocs = C4::Context->config('opachtdocs'); $theme = C4::Context->preference("opacthemes"); - $xslfile = C4::Context->preference('marcflavour') . - "slim2OPACResults.xsl"; + $xslfile = C4::Context->preference('marcflavour') . "slim2OPACResults.xsl"; } - $xslfilename = _get_best_default_xslt_filename($htdocs, $theme, $lang, $xslfile); + $xslfilename = _get_best_default_xslt_filename( $htdocs, $theme, $lang, $xslfile ); } if ( $xslfilename =~ m/\{langcode\}/ ) { @@ -198,7 +207,7 @@ sub get_xsl_filename { } sub XSLTParse4Display { - my ( $params ) = @_; + my ($params) = @_; my $biblionumber = $params->{biblionumber}; my $record = $params->{record}; @@ -213,12 +222,12 @@ sub XSLTParse4Display { die "Mandatory \$params->{xsl_syspref} was not provided, called with biblionumber $params->{biblionumber}" if not defined $params->{xsl_syspref}; - $xslfilename = get_xsl_filename( $xslsyspref, $xslfilename); + $xslfilename = get_xsl_filename( $xslsyspref, $xslfilename ); - my $frameworkcode = GetFrameworkCode($biblionumber) || ''; + my $frameworkcode = GetFrameworkCode($biblionumber) || ''; my $record_processor = Koha::RecordProcessor->new( { - filters => [ 'ExpandCodedFields' ], + filters => ['ExpandCodedFields'], options => { interface => $interface, frameworkcode => $frameworkcode @@ -229,24 +238,27 @@ sub XSLTParse4Display { # grab the XML, run it through our stylesheet, push it out to the browser my $itemsxml; - if ( $xslsyspref eq "OPACXSLTDetailsDisplay" || $xslsyspref eq "XSLTDetailsDisplay" || $xslsyspref eq "XSLTResultsDisplay" ) { - $itemsxml = ""; #We don't use XSLT for items display on these pages + if ( $xslsyspref eq "OPACXSLTDetailsDisplay" + || $xslsyspref eq "XSLTDetailsDisplay" + || $xslsyspref eq "XSLTResultsDisplay" ) + { + $itemsxml = ""; #We don't use XSLT for items display on these pages } else { - $itemsxml = buildKohaItemsNamespace($biblionumber, $hidden_items, $items_rs); + $itemsxml = buildKohaItemsNamespace( $biblionumber, $hidden_items, $items_rs ); } - my $xmlrecord = $record->as_xml(C4::Context->preference('marcflavour')); + my $xmlrecord = $record->as_xml( C4::Context->preference('marcflavour') ); $variables ||= {}; my $biblio; - if ( $interface eq 'opac' && C4::Context->preference('OPACShowOpenURL')) { + if ( $interface eq 'opac' && C4::Context->preference('OPACShowOpenURL') ) { my @biblio_itemtypes; $biblio //= Koha::Biblios->find($biblionumber); - if (C4::Context->preference('item-level_itypes')) { + if ( C4::Context->preference('item-level_itypes') ) { @biblio_itemtypes = $biblio->items->get_column("itype"); } else { push @biblio_itemtypes, $biblio->itemtype; } - my @itypes = split( /\s/, C4::Context->preference('OPACOpenURLItemTypes') ); + my @itypes = split( /\s/, C4::Context->preference('OPACOpenURLItemTypes') ); my %original = (); map { $original{$_} = 1 } @biblio_itemtypes; if ( grep { $original{$_} } @itypes ) { @@ -256,7 +268,7 @@ sub XSLTParse4Display { # embed variables my $varxml = "\n"; - while (my ($key, $value) = each %$variables) { + while ( my ( $key, $value ) = each %$variables ) { $value //= q{}; $varxml .= "$value\n"; } @@ -264,7 +276,7 @@ sub XSLTParse4Display { my $sysxml = get_xslt_sysprefs(); $xmlrecord =~ s/\<\/record\>/$itemsxml$sysxml$varxml\<\/record\>/; - if ($fixamps) { # We need to correct the ampersand entities that Zebra outputs + if ($fixamps) { # We need to correct the ampersand entities that Zebra outputs $xmlrecord =~ s/\&amp;/\&/g; $xmlrecord =~ s/\&\;lt\;/\<\;/g; $xmlrecord =~ s/\&\;gt\;/\>\;/g; @@ -275,7 +287,7 @@ sub XSLTParse4Display { #If the xslt should fail, we will return undef (old behavior was #raw MARC) #Note that we did set do_not_return_source at object construction - return $engine->transform($xmlrecord, $xslfilename ); #file or URL + return $engine->transform( $xmlrecord, $xslfilename ); #file or URL } =head2 buildKohaItemsNamespace @@ -294,13 +306,13 @@ Is only used in this module currently. =cut sub buildKohaItemsNamespace { - my ($biblionumber, $hidden_items, $items_rs) = @_; + my ( $biblionumber, $hidden_items, $items_rs ) = @_; $hidden_items ||= []; my $query = {}; $query = { 'me.itemnumber' => { not_in => $hidden_items } } - if $hidden_items; + if $hidden_items; unless ( $items_rs && ref($items_rs) eq 'Koha::Items' ) { $query->{'me.biblionumber'} = $biblionumber; @@ -309,17 +321,27 @@ sub buildKohaItemsNamespace { my $items = $items_rs->search( $query, { prefetch => [ 'branchtransfers', 'reserves' ] } ); - my $shelflocations = - { map { $_->{authorised_value} => $_->{opac_description} } Koha::AuthorisedValues->get_descriptions_by_koha_field( { frameworkcode => "", kohafield => 'items.location' } ) }; - my $ccodes = - { map { $_->{authorised_value} => $_->{opac_description} } Koha::AuthorisedValues->get_descriptions_by_koha_field( { frameworkcode => "", kohafield => 'items.ccode' } ) }; - - my %branches = map { $_->branchcode => $_->branchname } Koha::Libraries->search({}, { order_by => 'branchname' })->as_list; + my $shelflocations = { + map { $_->{authorised_value} => $_->{opac_description} } + Koha::AuthorisedValues->get_descriptions_by_koha_field( + { frameworkcode => "", kohafield => 'items.location' } + ) + }; + my $ccodes = { + map { $_->{authorised_value} => $_->{opac_description} } + Koha::AuthorisedValues->get_descriptions_by_koha_field( + { frameworkcode => "", kohafield => 'items.ccode' } + ) + }; + + my %branches = + map { $_->branchcode => $_->branchname } Koha::Libraries->search( {}, { order_by => 'branchname' } )->as_list; my $itemtypes = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search->unblessed } }; - my $xml = ''; - my %descs = map { $_->{authorised_value} => $_ } Koha::AuthorisedValues->get_descriptions_by_koha_field( { kohafield => 'items.notforloan' } ); - my $ref_status = C4::Context->preference('Reference_NFL_Statuses') // q{}; # fallback to 1|2 removed + my $xml = ''; + my %descs = map { $_->{authorised_value} => $_ } + Koha::AuthorisedValues->get_descriptions_by_koha_field( { kohafield => 'items.notforloan' } ); + my $ref_status = C4::Context->preference('Reference_NFL_Statuses') // q{}; # fallback to 1|2 removed while ( my $item = $items->next ) { my $status; @@ -327,81 +349,82 @@ sub buildKohaItemsNamespace { my $recalls_count; if ( C4::Context->preference('UseRecalls') ) { - $recalls_count = Koha::Recalls->search({ item_id => $item->itemnumber, status => 'waiting' })->count; + $recalls_count = Koha::Recalls->search( { item_id => $item->itemnumber, status => 'waiting' } )->count; } if ($recalls_count) { + # recalls take priority over holds - $status = 'other'; + $status = 'other'; $substatus = 'Recall waiting'; - } - elsif ( $item->has_pending_hold ) { - $status = 'other'; + } elsif ( $item->has_pending_hold ) { + $status = 'other'; $substatus = 'Pending hold'; - } - elsif ( $item->holds->waiting->count ) { - $status = 'other'; + } elsif ( $item->holds->waiting->count ) { + $status = 'other'; $substatus = 'Hold waiting'; - } - elsif ($item->get_transfer) { - $status = 'other'; + } elsif ( $item->get_transfer ) { + $status = 'other'; $substatus = 'In transit'; - } - elsif ($item->damaged) { - $status = 'other'; + } elsif ( $item->damaged ) { + $status = 'other'; $substatus = "Damaged"; - } - elsif ($item->itemlost) { - $status = 'other'; + } elsif ( $item->itemlost ) { + $status = 'other'; $substatus = "Lost"; - } - elsif ( $item->withdrawn) { - $status = 'other'; + } elsif ( $item->withdrawn ) { + $status = 'other'; $substatus = "Withdrawn"; - } - elsif ($item->onloan) { - $status = 'other'; + } elsif ( $item->onloan ) { + $status = 'other'; $substatus = "Checked out"; - } - elsif ( $item->notforloan ) { - $status = $item->notforloan =~ /^($ref_status)$/ + } elsif ( $item->notforloan ) { + $status = + $item->notforloan =~ /^($ref_status)$/ ? "reference" : "reallynotforloan"; - $substatus = exists $descs{$item->notforloan} ? $descs{$item->notforloan}->{opac_description} : "Not for loan"; - } - elsif ( exists $itemtypes->{ $item->effective_itemtype } + $substatus = + exists $descs{ $item->notforloan } ? $descs{ $item->notforloan }->{opac_description} : "Not for loan"; + } elsif ( exists $itemtypes->{ $item->effective_itemtype } && $itemtypes->{ $item->effective_itemtype }->{notforloan} && $itemtypes->{ $item->effective_itemtype }->{notforloan} == 1 ) { - $status = "1" =~ /^($ref_status)$/ + $status = + "1" =~ /^($ref_status)$/ ? "reference" : "reallynotforloan"; $substatus = "Not for loan"; - } - else { + } else { $status = "available"; } - my $homebranch = C4::Koha::xml_escape($branches{$item->homebranch}); - my $holdingbranch = C4::Koha::xml_escape($branches{$item->holdingbranch}); - my $resultbranch = C4::Context->preference('OPACResultsLibrary') eq 'homebranch' ? $homebranch : $holdingbranch; - my $location = C4::Koha::xml_escape($item->location && exists $shelflocations->{$item->location} ? $shelflocations->{$item->location} : $item->location); - my $ccode = C4::Koha::xml_escape($item->ccode && exists $ccodes->{$item->ccode} ? $ccodes->{$item->ccode} : $item->ccode); - my $itemcallnumber = C4::Koha::xml_escape($item->itemcallnumber); - my $stocknumber = C4::Koha::xml_escape($item->stocknumber); + my $homebranch = C4::Koha::xml_escape( $branches{ $item->homebranch } ); + my $holdingbranch = C4::Koha::xml_escape( $branches{ $item->holdingbranch } ); + my $resultbranch = C4::Context->preference('OPACResultsLibrary') eq 'homebranch' ? $homebranch : $holdingbranch; + my $location = C4::Koha::xml_escape( + $item->location && exists $shelflocations->{ $item->location } + ? $shelflocations->{ $item->location } + : $item->location + ); + my $ccode = C4::Koha::xml_escape( $item->ccode + && exists $ccodes->{ $item->ccode } ? $ccodes->{ $item->ccode } : $item->ccode ); + my $itemcallnumber = C4::Koha::xml_escape( $item->itemcallnumber ); + my $stocknumber = C4::Koha::xml_escape( $item->stocknumber ); $xml .= - "" - . "$homebranch" - . "$holdingbranch" - . "$resultbranch" - . "$location" - . "$ccode" - . "".( $status // q{} )."" - . "$substatus" - . "$itemcallnumber" - . "$stocknumber" - . ""; + "" + . "$homebranch" + . "$holdingbranch" + . "$resultbranch" + . "$location" + . "$ccode" + . "" + . ( $status // q{} ) + . "" + . "$substatus" + . "$itemcallnumber" + . "$stocknumber" + . ""; } - $xml = "".$xml.""; + $xml = "" . $xml . ""; return $xml; } @@ -422,52 +445,57 @@ sub engine { =cut sub CustomXSLTExportList { - my $opac = shift; # opac (1) vs intranet (0) + my $opac = shift; # opac (1) vs intranet (0) return [] if $opac && C4::Context->preference('OpacExportOptions') !~ /custom/; + my $customXSLTExportPath = C4::Context->preference('CustomXSLTExportPath'); + # Check the cache first - my $cache = Koha::Caches->get_instance; - my $key = $opac ? 'CustomXSLTExportListOPAC' : 'CustomXSLTExportListIntra'; + my $cache = Koha::Caches->get_instance; + my $key = $opac ? 'CustomXSLTExportListOPAC' : 'CustomXSLTExportListIntra'; my $cached_val = $cache->get_from_cache($key); return $cached_val if $cached_val; my @tabFiles; - my $dir = C4::Context->config( $opac ? 'opachtdocs' : 'intrahtdocs') . - '/' . C4::Context->preference( $opac ? "opacthemes" : "template") . - '/' . C4::Languages::getlanguage() . - '/xslt/biblioexport'; + my $dir = + $customXSLTExportPath ? + $customXSLTExportPath : + C4::Context->config( $opac ? 'opachtdocs' : 'intrahtdocs' ) . '/' + . C4::Context->preference( $opac ? "opacthemes" : "template" ) . '/' + . C4::Languages::getlanguage() + . '/xslt/biblioexport'; my @files = glob qq("$dir/*.xsl"); foreach my $file (@files) { if ( -f "$file" ) { - (my $text = $file) =~ s/.*\///g; + ( my $text = $file ) =~ s/.*\///g; ## Get title of the option my $dom; eval { $dom = XML::LibXML->load_xml( location => $file ); }; next unless $dom; - my $node = $dom->documentElement(); + my $node = $dom->documentElement(); my $title = $node->{"title"}; - ($title = $text) =~ s/\.xsl// unless defined $title; + ( $title = $text ) =~ s/\.xsl// unless defined $title; # Get output format # There should only be one xsl:output node, so taking the first one only is OK - $node = @{$node->findnodes("xsl:output")}[0]; - my $outputformat= ""; + $node = @{ $node->findnodes("xsl:output") }[0]; + my $outputformat = ""; $outputformat = $node->{"method"} if $node; - $outputformat = "txt" if ($outputformat eq "" || $outputformat eq "text"); + $outputformat = "txt" if ( $outputformat eq "" || $outputformat eq "text" ); my %row = ( - value => $text, - filename => $title, - format => $outputformat, + value => $text, + filename => $title, + format => $outputformat, ); push @tabFiles, \%row; } } - $cache->set_in_cache( $key, [ @tabFiles ] ); + $cache->set_in_cache( $key, [@tabFiles] ); return \@tabFiles; } 1; --- a/basket/basket.pl +++ a/basket/basket.pl @@ -112,9 +112,9 @@ my $resultsarray = \@results; $template->param( BIBLIO_RESULTS => $resultsarray, - csv_profiles => Koha::CsvProfiles->search({ type => 'marc', used_for => 'export_records' }), - xsl_exports => CustomXSLTExportList(), - bib_list => $bib_list, + csv_profiles => Koha::CsvProfiles->search({ type => 'marc', used_for => 'export_records' }), + xsl_exports => CustomXSLTExportList(), + bib_list => $bib_list, ); output_html_with_http_headers $query, $cookie, $template->output; --- a/basket/downloadcart.pl +++ a/basket/downloadcart.pl @@ -34,78 +34,79 @@ use Koha::Biblios; use utf8; my $query = CGI->new; -my ( $template, $borrowernumber, $cookie ) = get_template_and_user ( +my ( $template, $borrowernumber, $cookie ) = get_template_and_user( { - template_name => "basket/downloadcart.tt", - query => $query, - type => "intranet", - flagsrequired => { catalogue => 1 }, + template_name => "basket/downloadcart.tt", + query => $query, + type => "intranet", + flagsrequired => { catalogue => 1 }, } ); my $bib_list = $query->param('bib_list'); -my $format = $query->param('format'); -my $dbh = C4::Context->dbh; +my $format = $query->param('format'); +my $dbh = C4::Context->dbh; -if ($bib_list && $format) { +if ( $bib_list && $format ) { my @bibs = split( /\//, $bib_list ); - my $marcflavour = C4::Context->preference('marcflavour'); + my $marcflavour = C4::Context->preference('marcflavour'); my $output; - # CSV - if ($format =~ /^\d+$/) { + # CSV + if ( $format =~ /^\d+$/ ) { - $output = marc2csv(\@bibs, $format); - - # Other formats + $output = marc2csv( \@bibs, $format ); + + # Other formats } else { foreach my $biblionumber (@bibs) { - my $biblio = Koha::Biblios->find($biblionumber); - my $record = $biblio->metadata->record({ embed_items => 1 }); + my $biblio = Koha::Biblios->find($biblionumber); + my $record = $biblio->metadata->record( { embed_items => 1 } ); my $xslFile = $query->param("file"); next unless $record; - if ($format eq 'iso2709') { + if ( $format eq 'iso2709' ) { + #NOTE: If we don't explicitly UTF-8 encode the output, #the browser will guess the encoding, and it won't always choose UTF-8. - $output .= encode("UTF-8", $record->as_usmarc()) // q{}; - } - elsif ($format eq 'ris') { + $output .= encode( "UTF-8", $record->as_usmarc() ) // q{}; + } elsif ( $format eq 'ris' ) { $output .= marc2ris($record); - } - elsif ($format eq 'bibtex') { - $output .= marc2bibtex($record, $biblionumber); - } - elsif ($format =~ /^xsl\.(.*)$/) { - $output .= XSLTParse4Display({ - biblionumber => $biblio, - record => $record, - xsl_syspref => "XSLTCustomExport", - fix_amps => 1, - hidden_items => undef, - xslfilename => $xslFile, - }); + } elsif ( $format eq 'bibtex' ) { + $output .= marc2bibtex( $record, $biblionumber ); + } elsif ( $format =~ /^xsl\.(.*)$/ ) { + $output .= XSLTParse4Display( + { + biblionumber => $biblio, + record => $record, + xsl_syspref => "XSLTCustomExport", + fix_amps => 1, + hidden_items => undef, + xslfilename => $xslFile, + } + ); } } } # If it was a CSV export we change the format after the export so the file extension is fine - $format = "csv" if ($format =~ m/^\d+$/); - $format = "html" if ($format =~ /^xsl\./); + $format = "csv" if ( $format =~ m/^\d+$/ ); + $format = "html" if ( $format =~ /^xsl\./ ); print $query->header( - -type => 'application/octet-stream', - -'Content-Transfer-Encoding' => 'binary', - -attachment=>"cart.$format"); + -type => 'application/octet-stream', + -'Content-Transfer-Encoding' => 'binary', + -attachment => "cart.$format" + ); print $output; -} else { - $template->param(csv_profiles => Koha::CsvProfiles->search({ type => 'marc', used_for => 'export_records' })); - $template->param(xsl_exports => CustomXSLTExportList()); - $template->param(bib_list => $bib_list); +} else { + $template->param( csv_profiles => Koha::CsvProfiles->search( { type => 'marc', used_for => 'export_records' } ) ); + $template->param( xsl_exports => CustomXSLTExportList() ); + $template->param( bib_list => $bib_list ); output_html_with_http_headers $query, $cookie, $template->output; } --- a/catalogue/detail.pl +++ a/catalogue/detail.pl @@ -85,8 +85,8 @@ if ( C4::Context->config('enable_plugins') ) { ); } -##### ADD CUSTOM XSLT -$template->param(filesOptions => CustomXSLTExportList(0)); +# Add custom XSLT +$template->param( filesOptions => CustomXSLTExportList(0) ); my $biblionumber = $query->param('biblionumber'); $biblionumber = HTML::Entities::encode($biblionumber); --- a/catalogue/export.pl +++ a/catalogue/export.pl @@ -10,106 +10,101 @@ use C4::Ris qw( marc2ris ); use C4::XSLT qw( XSLTParse4Display ); use Koha::Biblios; - - my $query = CGI->new; -my ( $template, $loggedinuser, $cookie ) = get_template_and_user({ - template_name => "tools/export.tt", - query => $query, - type => "intranet", - flagsrequired => { catalogue => 1 }, - }); +my ( $template, $loggedinuser, $cookie ) = get_template_and_user( + { + template_name => "tools/export.tt", + query => $query, + type => "intranet", + flagsrequired => { catalogue => 1 }, + } +); -my $op=$query->param("op"); -my $format=$query->param("format"); -my $error = ''; -if ($op eq "export") { +my $op = $query->param("op"); +my $format = $query->param("format"); +my $error = ''; +if ( $op eq "export" ) { my $biblionumber = $query->param("bib"); - if ($biblionumber){ - my $file_id = $biblionumber; - my $file_pre = "bib-"; + if ($biblionumber) { + my $file_id = $biblionumber; + my $file_pre = "bib-"; - my $biblio = Koha::Biblios->find($biblionumber); - my $marc = $biblio->metadata->record({ embed_items => 1 }); + my $biblio = Koha::Biblios->find($biblionumber); + my $marc = $biblio->metadata->record( { embed_items => 1 } ); - if( C4::Context->preference('DefaultSaveRecordFileID') eq 'controlnumber' ){ - my $marcflavour = C4::Context->preference('marcflavour'); #FIXME This option is required but does not change control num behaviour - my $control_num = GetMarcControlnumber( $marc, $marcflavour ); - if( $control_num ){ - $file_id = $control_num; - $file_pre = "record-"; - } + if ( C4::Context->preference('DefaultSaveRecordFileID') eq 'controlnumber' ) { + my $marcflavour = C4::Context->preference('marcflavour') + ; #FIXME This option is required but does not change control num behaviour + my $control_num = GetMarcControlnumber( $marc, $marcflavour ); + if ($control_num) { + $file_id = $control_num; + $file_pre = "record-"; } + } - if ($format =~ /endnote/) { - $marc = marc2endnote($marc); - $format = 'endnote'; - } - elsif ($format =~ /marcxml/) { - $marc = marc2marcxml($marc); - $format = "marcxml"; - } - elsif ($format=~ /mods/) { - $marc = marc2modsxml($marc); - $format = "mods"; - } - elsif ($format =~ /ris/) { - $marc = marc2ris($marc); - $format = "ris"; - } - elsif ($format =~ /bibtex/) { - $marc = marc2bibtex($marc); - $format = "bibtex"; - } - elsif ($format =~ /dc$/) { - $marc = marc2dcxml(undef, undef, $biblionumber, $format); - $format = "dublin-core.xml"; - } - elsif ($format =~ /marc8/) { - $marc = changeEncoding($marc,"MARC","MARC21","MARC-8"); - $marc = $marc->as_usmarc(); - $format = "marc8"; - } - elsif ($format =~ /utf8/) { - C4::Charset::SetUTF8Flag($marc, 1); - $marc = $marc->as_usmarc(); - $format = "utf8"; - } - elsif ($format =~ /marcstd/) { - C4::Charset::SetUTF8Flag($marc,1); - ($error, $marc) = marc2marc($marc, 'marcstd', C4::Context->preference('marcflavour')); - $format = "marcstd"; - } - if ( $format =~ /utf8/ or $format =~ /marcstd/ ) { - binmode STDOUT, ':encoding(UTF-8)'; - } - print $query->header( - -type => 'application/octet-stream', - -attachment=>"$file_pre$file_id.$format"); - print $marc; + if ( $format =~ /endnote/ ) { + $marc = marc2endnote($marc); + $format = 'endnote'; + } elsif ( $format =~ /marcxml/ ) { + $marc = marc2marcxml($marc); + $format = "marcxml"; + } elsif ( $format =~ /mods/ ) { + $marc = marc2modsxml($marc); + $format = "mods"; + } elsif ( $format =~ /ris/ ) { + $marc = marc2ris($marc); + $format = "ris"; + } elsif ( $format =~ /bibtex/ ) { + $marc = marc2bibtex($marc); + $format = "bibtex"; + } elsif ( $format =~ /dc$/ ) { + $marc = marc2dcxml( undef, undef, $biblionumber, $format ); + $format = "dublin-core.xml"; + } elsif ( $format =~ /marc8/ ) { + $marc = changeEncoding( $marc, "MARC", "MARC21", "MARC-8" ); + $marc = $marc->as_usmarc(); + $format = "marc8"; + } elsif ( $format =~ /utf8/ ) { + C4::Charset::SetUTF8Flag( $marc, 1 ); + $marc = $marc->as_usmarc(); + $format = "utf8"; + } elsif ( $format =~ /marcstd/ ) { + C4::Charset::SetUTF8Flag( $marc, 1 ); + ( $error, $marc ) = marc2marc( $marc, 'marcstd', C4::Context->preference('marcflavour') ); + $format = "marcstd"; + } + if ( $format =~ /utf8/ or $format =~ /marcstd/ ) { + binmode STDOUT, ':encoding(UTF-8)'; } -}elsif ($op eq "exportxsl"){ + print $query->header( + -type => 'application/octet-stream', + -attachment => "$file_pre$file_id.$format" + ); + print $marc; + } +} elsif ( $op eq "exportxsl" ) { my $biblionumber = $query->param("bib"); - if ($biblionumber){ + if ($biblionumber) { my $xslFile = $query->param("file"); - my $biblio = Koha::Biblios->find($biblionumber); - my $marc = $biblio->metadata->record( { embed_items => 1 } ); - my $format=$query->param("format")||'txt'; + my $biblio = Koha::Biblios->find($biblionumber); + my $marc = $biblio->metadata->record( { embed_items => 1 } ); + my $format = $query->param("format") || 'txt'; my @hiddenitems; $marc = XSLTParse4Display( { - biblionumber => $biblionumber, - record => $marc, - xsl_syspref => "XSLTCustomExport", - fix_amps => 1, - hidden_items => \@hiddenitems, - xslfilename => $xslFile, + biblionumber => $biblionumber, + record => $marc, + xsl_syspref => "XSLTCustomExport", + fix_amps => 1, + hidden_items => \@hiddenitems, + xslfilename => $xslFile, } ); print $query->header( - -type => 'application/octet-stream', - -attachment=>"bib-$biblionumber.$format"); + -type => 'application/octet-stream', + -attachment => "bib-$biblionumber.$format" + ); print $marc; } } --- a/installer/data/mysql/atomicupdate/bug_17385-CustomOptionForOpacExportOptions_syspref.pl +++ a/installer/data/mysql/atomicupdate/bug_17385-CustomOptionForOpacExportOptions_syspref.pl @@ -0,0 +1,29 @@ +use Modern::Perl; + +return { + bug_number => "17385", + description => "Add a custom option for OpacExportOptions system preference", + up => sub { + my ($args) = @_; + my ( $dbh, $out ) = @$args{qw(dbh out)}; + + $dbh->do( + q{ + UPDATE systempreferences + SET value = 'bibtex,dc,marcxml,marc8,utf8,marcstd,mods,ris,isbd,custom' + WHERE variable = 'OpacExportOptions'; + } + ); + + $dbh->do( + q{ + INSERT IGNORE INTO systempreferences (variable,value,options,explanation,type) + VALUES ('CustomXSLTExportPath','','','The path to the folder containing the customized XSL files for export',''); + } + ); + + # sysprefs + say $out "Updated system preference 'OpacExportOptions'"; + say $out "Added new system preference 'OpacCustomExportFilePath'"; + }, +}; --- a/installer/data/mysql/mandatory/sysprefs.sql +++ a/installer/data/mysql/mandatory/sysprefs.sql @@ -176,6 +176,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('CurrencyFormat','US','US|FR|CH','Determines the display format of currencies. eg: \'36000\' is displayed as \'360 000,00\' in \'FR\' or \'360,000.00\' in \'US\'.','Choice'), ('CustomCoverImages','0',NULL,'If enabled, the custom cover images will be displayed in the staff interface. CustomCoverImagesURL must be defined.','YesNo'), ('CustomCoverImagesURL','',NULL,'Define an URL serving book cover images, using the following patterns: %issn%, %isbn%, FIXME ADD MORE (use it with CustomCoverImages and/or OPACCustomCoverImages)','free'), +('CustomXSLTExportPath','','','The path to the folder containing the customized XSL files for export',''), ('dateformat','us','metric|us|iso|dmydot','Define global date format (us mm/dd/yyyy, metric dd/mm/yyy, ISO yyyy-mm-dd, dmydot dd.mm.yyyy)','Choice'), ('DebugLevel','2','0|1|2','Define the level of debugging information sent to the browser when errors are encountered (set to 0 in production). 0=none, 1=some, 2=most','Choice'), ('decreaseLoanHighHolds','0','','Decreases the loan period for items with number of holds above the threshold specified in decreaseLoanHighHoldsValue','YesNo'), @@ -463,7 +464,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('OPACdefaultSortOrder','dsc','asc|dsc|za|az','Specify the default sort order','Choice'), ('OPACdidyoumean','',NULL,'Did you mean? configuration for the OPAC. Do not change, as this is controlled by /cgi-bin/koha/admin/didyoumean.pl.','Free'), ('OPACDisplay856uAsImage','OFF','OFF|Details|Results|Both','Display the URI in the 856u field as an image, the corresponding OPACXSLT option must be on','Choice'), -('OpacExportOptions','bibtex,dc,marcxml,marc8,utf8,marcstd,mods,ris,isbd','','Define export options available on OPAC detail page.','multiple'), +('OpacExportOptions','bibtex,dc,marcxml,marc8,utf8,marcstd,mods,ris,isbd,custom','','Define export options available on OPAC detail page.','multiple'), ('OPACFallback', 'prog', 'bootstrap|prog', 'Define the fallback theme for the OPAC interface.', 'Themes'), ('OpacFavicon','','','Enter a complete URL to an image to replace the default Koha favicon on the OPAC','free'), ('OPACFineNoRenewals','100','','Fine limit above which user cannot renew books via OPAC','Integer'), --- a/koha-tmpl/intranet-tmpl/prog/en/includes/cat-toolbar.inc +++ a/koha-tmpl/intranet-tmpl/prog/en/includes/cat-toolbar.inc @@ -107,7 +107,7 @@
  • MODS (XML)
  • RIS
  • [% FOREACH filesOption IN filesOptions %] -
  • XSL - [% filesOption.filename | html %]
  • +
  • [% filesOption.filename | html %]
  • [% END %] --- a/koha-tmpl/intranet-tmpl/prog/en/includes/virtualshelves-toolbar.inc +++ a/koha-tmpl/intranet-tmpl/prog/en/includes/virtualshelves-toolbar.inc @@ -39,7 +39,7 @@
  • CSV - [% csv_profile.profile | html %]
  • [% END %] [% FOREACH xsl_export IN xsl_exports %] -
  • XSL - [% xsl_export.filename | html %]
  • +
  • [% xsl_export.filename | html %]
  • [% END %] --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/cataloguing.pref +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/cataloguing.pref @@ -384,6 +384,11 @@ Cataloging: - "All values of repeating tags and subfields will be printed with the given BibTeX tag." - "
    " - "Use '@' ( with quotes ) as the BT_TAG to replace the bibtex record type with a field value of your choosing." + - + - "Use this" + - pref: CustomXSLTExportPath + class: long + - "as the path containing the customized XSL files for export (write the complete path)." - - "Include the following fields when exporting RIS:" - pref: RisExportAdditionalFields --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref @@ -280,7 +280,7 @@ OPAC: mods: MODS ris: RIS isbd: ISBD - custom: XSL - Simple Export + custom: Simple HTML formats - - pref: OpacSeparateHoldings choices: --- a/koha-tmpl/intranet-tmpl/prog/en/modules/basket/basket.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/basket/basket.tt @@ -64,7 +64,7 @@
  • CSV - [% csv_profile.profile | html %]
  • [% END %] [% FOREACH xsl_export IN xsl_exports %] -
  • XSL - [% xsl_export.filename | html %]
  • +
  • [% xsl_export.filename | html %]
  • [% END %] --- a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt @@ -1099,7 +1099,7 @@ [% FOREACH filesOption IN filesOptions %] - + [% END %] --- a/koha-tmpl/intranet-tmpl/prog/en/modules/virtualshelves/downloadshelf.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/virtualshelves/downloadshelf.tt @@ -43,7 +43,7 @@ [% END %] [% FOREACH xsl_export IN xsl_exports %] - + [% END %] --- a/koha-tmpl/intranet-tmpl/prog/en/xslt/biblioexport/MARC21_simple_export.xsl +++ a/koha-tmpl/intranet-tmpl/prog/en/xslt/biblioexport/MARC21_simple_export.xsl @@ -1,62 +1,89 @@ - + + + + - + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:marc="http://www.loc.gov/MARC21/slim" + exclude-result-prefixes="marc" + title="Simple Export"> + + - + <!DOCTYPE html> + + + + + + Simple Export + + + + + + -

    - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - -
    - -
    - - - +

    + + + + + + + + + + + + + + - - - + + +
    + + + + + + + + + + + + + + +
    - - - + + +
    + + + + + + + + + + + + + + +
    - -
    -

    +

    - -
    + --- a/koha-tmpl/opac-tmpl/bootstrap/en/includes/opac-detail-sidebar.inc +++ a/koha-tmpl/opac-tmpl/bootstrap/en/includes/opac-detail-sidebar.inc @@ -87,7 +87,7 @@ [% ELSE %] [% FOREACH filesOption IN filesOptions %] - XSL - [% filesOption.filename | html %] + [% filesOption.filename | html %] [% END %] [% END %] [% END %] --- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-basket.tt +++ a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-basket.tt @@ -44,7 +44,7 @@ [% FOREACH option IN export_options %] [% IF option == 'custom' %] [% FOREACH xsl_export IN xsl_exports %] - XSL - [% xsl_export.filename | html %] + [% xsl_export.filename | html %] [% END %] [% END %] [% END %] --- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-downloadcart.tt +++ a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-downloadcart.tt @@ -21,7 +21,7 @@ [% END %] [% FOREACH xsl_export IN xsl_exports %] - + [% END %]
    --- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-downloadshelf.tt +++ a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-downloadshelf.tt @@ -69,7 +69,7 @@ [% END %] [% FOREACH xsl_export IN xsl_exports %] - + [% END %] Required --- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-shelves.tt +++ a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-shelves.tt @@ -237,7 +237,7 @@ [% FOREACH option IN export_options %] [% IF option == 'custom' %] [% FOREACH xsl_export IN xsl_exports %] - XSL - [% xsl_export.filename | html %] + [% xsl_export.filename | html %] [% END %] [% END %] [% END %] --- a/opac/opac-basket.pl +++ a/opac/opac-basket.pl @@ -37,7 +37,7 @@ use Koha::Items; my $query = CGI->new; -my ( $template, $borrowernumber, $cookie ) = get_template_and_user ( +my ( $template, $borrowernumber, $cookie ) = get_template_and_user( { template_name => "opac-basket.tt", query => $query, @@ -46,64 +46,66 @@ my ( $template, $borrowernumber, $cookie ) = get_template_and_user ( } ); -my $bib_list = $query->param('bib_list'); -my $verbose = $query->param('verbose'); +my $bib_list = $query->param('bib_list'); +my $verbose = $query->param('verbose'); -if ($verbose) { $template->param( verbose => 1 ); } +if ($verbose) { $template->param( verbose => 1 ); } my @bibs = split( /\//, $bib_list ); my @results; -my $num = 1; +my $num = 1; my $marcflavour = C4::Context->preference('marcflavour'); -if (C4::Context->preference('TagsEnabled')) { - $template->param(TagsEnabled => 1); - foreach (qw(TagsShowOnList TagsInputOnList)) { - C4::Context->preference($_) and $template->param($_ => 1); - } +if ( C4::Context->preference('TagsEnabled') ) { + $template->param( TagsEnabled => 1 ); + foreach (qw(TagsShowOnList TagsInputOnList)) { + C4::Context->preference($_) and $template->param( $_ => 1 ); + } } my $logged_in_user = Koha::Patrons->find($borrowernumber); -my $record_processor = Koha::RecordProcessor->new({ filters => 'ViewPolicy' }); -my $rules = C4::Context->yaml_preference('OpacHiddenItems'); +my $record_processor = Koha::RecordProcessor->new( { filters => 'ViewPolicy' } ); +my $rules = C4::Context->yaml_preference('OpacHiddenItems'); -foreach my $biblionumber ( @bibs ) { +foreach my $biblionumber (@bibs) { $template->param( biblionumber => $biblionumber ); - my $biblio = Koha::Biblios->find( $biblionumber ) or next; - my $dat = { %{$biblio->unblessed}, %{$biblio->biblioitem->unblessed} }; + my $biblio = Koha::Biblios->find($biblionumber) or next; + my $dat = { %{ $biblio->unblessed }, %{ $biblio->biblioitem->unblessed } }; # No filtering on the item records needed for the record itself # since the only reason item information is grabbed is because of branchcodes. - my $record = $biblio->metadata->record; - my $framework = &GetFrameworkCode( $biblionumber ); - $record_processor->options({ - interface => 'opac', - frameworkcode => $framework - }); + my $record = $biblio->metadata->record; + my $framework = &GetFrameworkCode($biblionumber); + $record_processor->options( + { + interface => 'opac', + frameworkcode => $framework + } + ); $record_processor->process($record); next unless $record; - my $marcnotesarray = $biblio->get_marc_notes({ opac => 1 }); + my $marcnotesarray = $biblio->get_marc_notes( { opac => 1 } ); my $marcauthorsarray = $biblio->get_marc_contributors; my $marcsubjctsarray = GetMarcSubjects( $record, $marcflavour ); - my $marcseriesarray = GetMarcSeries ($record,$marcflavour); - my $marcurlsarray = GetMarcUrls ($record,$marcflavour); + my $marcseriesarray = GetMarcSeries( $record, $marcflavour ); + my $marcurlsarray = GetMarcUrls( $record, $marcflavour ); # If every item is hidden, then the biblio should be hidden too. next - if $biblio->hidden_in_opac({ rules => $rules }); + if $biblio->hidden_in_opac( { rules => $rules } ); my $hasauthors = 0; - if($dat->{'author'} || @$marcauthorsarray) { - $hasauthors = 1; + if ( $dat->{'author'} || @$marcauthorsarray ) { + $hasauthors = 1; } - # COinS format FIXME: for books Only - my $fmt = substr $record->leader(), 6,2; - my $fmts; - $fmts->{'am'} = 'book'; - $dat->{ocoins_format} = $fmts->{$fmt}; + # COinS format FIXME: for books Only + my $fmt = substr $record->leader(), 6, 2; + my $fmts; + $fmts->{'am'} = 'book'; + $dat->{ocoins_format} = $fmts->{$fmt}; if ( $num % 2 == 1 ) { $dat->{'even'} = 1; @@ -111,17 +113,17 @@ foreach my $biblionumber ( @bibs ) { $num++; $dat->{biblionumber} = $biblionumber; - $dat->{ITEM_RESULTS} = $biblio->items->filter_by_visible_in_opac({ patron => $logged_in_user }); - $dat->{MARCNOTES} = $marcnotesarray; - $dat->{MARCSUBJCTS} = $marcsubjctsarray; - $dat->{MARCAUTHORS} = $marcauthorsarray; - $dat->{MARCSERIES} = $marcseriesarray; - $dat->{MARCURLS} = $marcurlsarray; - $dat->{HASAUTHORS} = $hasauthors; + $dat->{ITEM_RESULTS} = $biblio->items->filter_by_visible_in_opac( { patron => $logged_in_user } ); + $dat->{MARCNOTES} = $marcnotesarray; + $dat->{MARCSUBJCTS} = $marcsubjctsarray; + $dat->{MARCAUTHORS} = $marcauthorsarray; + $dat->{MARCSERIES} = $marcseriesarray; + $dat->{MARCURLS} = $marcurlsarray; + $dat->{HASAUTHORS} = $hasauthors; my ( $host, $relatedparts, $hostinfo ) = $biblio->get_marc_host; $dat->{HOSTITEMENTRIES} = $host; - $dat->{RELATEDPARTS} = $relatedparts; - $dat->{HOSTINFO} = $hostinfo; + $dat->{RELATEDPARTS} = $relatedparts; + $dat->{HOSTINFO} = $hostinfo; push( @results, $dat ); } @@ -131,11 +133,10 @@ my $resultsarray = \@results; # my $itemsarray=\@items; $template->param( - csv_profiles => Koha::CsvProfiles->search( - { type => 'marc', used_for => 'export_records', staff_only => 0 } ), - bib_list => $bib_list, + csv_profiles => Koha::CsvProfiles->search( { type => 'marc', used_for => 'export_records', staff_only => 0 } ), + bib_list => $bib_list, BIBLIO_RESULTS => $resultsarray, - xsl_exports => CustomXSLTExportList(), + xsl_exports => CustomXSLTExportList(), ); output_html_with_http_headers $query, $cookie, $template->output, undef, { force_no_caching => 1 }; --- a/opac/opac-detail.pl +++ a/opac/opac-detail.pl @@ -103,7 +103,7 @@ my ( $template, $borrowernumber, $cookie ) = get_template_and_user( } ); -$template->param(filesOptions => CustomXSLTExportList(1)); +$template->param( filesOptions => CustomXSLTExportList(1) ); my $patron = Koha::Patrons->find( $borrowernumber ); --- a/opac/opac-downloadcart.pl +++ a/opac/opac-downloadcart.pl @@ -36,7 +36,7 @@ use Koha::RecordProcessor; use utf8; my $query = CGI->new(); -my ( $template, $borrowernumber, $cookie ) = get_template_and_user ( +my ( $template, $borrowernumber, $cookie ) = get_template_and_user( { template_name => "opac-downloadcart.tt", query => $query, @@ -46,10 +46,10 @@ my ( $template, $borrowernumber, $cookie ) = get_template_and_user ( ); my $bib_list = $query->param('bib_list'); -my $format = $query->param('format'); -my $dbh = C4::Context->dbh; +my $format = $query->param('format'); +my $dbh = C4::Context->dbh; -if ($bib_list && $format) { +if ( $bib_list && $format ) { my $patron = Koha::Patrons->find($borrowernumber); @@ -60,8 +60,8 @@ if ($bib_list && $format) { my $extension; my $type; - # CSV - if ($format =~ /^\d+$/) { + # CSV + if ( $format =~ /^\d+$/ ) { my $csv_profile = Koha::CsvProfiles->find($format); if ( not $csv_profile or $csv_profile->staff_only ) { @@ -69,13 +69,11 @@ if ($bib_list && $format) { exit; } - $output = marc2csv(\@bibs, $format); + $output = marc2csv( \@bibs, $format ); # Other formats } else { - my $record_processor = Koha::RecordProcessor->new({ - filters => 'ViewPolicy' - }); + my $record_processor = Koha::RecordProcessor->new( { filters => 'ViewPolicy' } ); foreach my $biblionumber (@bibs) { my $biblio = Koha::Biblios->find($biblionumber); @@ -86,62 +84,65 @@ if ($bib_list && $format) { patron => $patron, } ); - my $xslFile = $query->param("file"); - my $framework = &GetFrameworkCode( $biblio ); - $record_processor->options({ - interface => 'opac', - frameworkcode => $framework - }); + my $xslFile = $query->param("file"); + my $framework = &GetFrameworkCode($biblio); + $record_processor->options( + { + interface => 'opac', + frameworkcode => $framework + } + ); $record_processor->process($record); next unless $record; - if ($format eq 'iso2709') { + if ( $format eq 'iso2709' ) { + #NOTE: If we don't explicitly UTF-8 encode the output, #the browser will guess the encoding, and it won't always choose UTF-8. - $output .= encode("UTF-8", $record->as_usmarc()) // q{}; - } - elsif ($format eq 'ris') { + $output .= encode( "UTF-8", $record->as_usmarc() ) // q{}; + } elsif ( $format eq 'ris' ) { $output .= marc2ris($record); - } - elsif ($format eq 'bibtex') { - $output .= marc2bibtex($record, $biblio); - } - elsif ( $format eq 'isbd' ) { - my $framework = GetFrameworkCode( $biblio ); - $output .= GetISBDView({ - 'record' => $record, - 'template' => 'opac', - 'framework' => $framework, - }); + } elsif ( $format eq 'bibtex' ) { + $output .= marc2bibtex( $record, $biblio ); + } elsif ( $format eq 'isbd' ) { + my $framework = GetFrameworkCode($biblio); + $output .= GetISBDView( + { + 'record' => $record, + 'template' => 'opac', + 'framework' => $framework, + } + ); $extension = "txt"; $type = "text/plain"; - } - elsif ($format =~ /^xsl\.(.*)$/) { - $output .= XSLTParse4Display({ - biblionumber => $biblio, - record => $record, - xsl_syspref => "OPACXSLTCustomExport", - fix_amps => 1, - hidden_items => undef, - xslfilename => $xslFile, - }); + } elsif ( $format =~ /^xsl\.(.*)$/ ) { + $output .= XSLTParse4Display( + { + biblionumber => $biblio, + record => $record, + xsl_syspref => "OPACXSLTCustomExport", + fix_amps => 1, + hidden_items => undef, + xslfilename => $xslFile, + } + ); } } } # If it was a CSV export we change the format after the export so the file extension is fine - $format = "csv" if ($format =~ m/^\d+$/); - $format = "html" if ($format =~ /^xsl\./); + $format = "csv" if ( $format =~ m/^\d+$/ ); + $format = "html" if ( $format =~ /^xsl\./ ); print $query->header( - -type => ($type) ? $type : 'application/octet-stream', + -type => ($type) ? $type : 'application/octet-stream', -'Content-Transfer-Encoding' => 'binary', - -attachment => ($extension) ? "cart.$format.$extension" : "cart.$format" + -attachment => ($extension) ? "cart.$format.$extension" : "cart.$format" ); print $output; -} else { +} else { $template->param( csv_profiles => Koha::CsvProfiles->search( { @@ -152,7 +153,7 @@ if ($bib_list && $format) { ), bib_list => $bib_list, ); - $template->param(bib_list => $bib_list); - $template->param(xsl_exports => CustomXSLTExportList()); + $template->param( bib_list => $bib_list ); + $template->param( xsl_exports => CustomXSLTExportList() ); output_html_with_http_headers $query, $cookie, $template->output; } --- a/opac/opac-downloadshelf.pl +++ a/opac/opac-downloadshelf.pl @@ -37,12 +37,12 @@ use utf8; my $query = CGI->new; # if virtualshelves is disabled, leave immediately -if ( ! C4::Context->preference('virtualshelves') ) { +if ( !C4::Context->preference('virtualshelves') ) { print $query->redirect("/cgi-bin/koha/errors/404.pl"); exit; } -my ( $template, $borrowernumber, $cookie ) = get_template_and_user ( +my ( $template, $borrowernumber, $cookie ) = get_template_and_user( { template_name => "opac-downloadshelf.tt", query => $query, @@ -51,26 +51,25 @@ my ( $template, $borrowernumber, $cookie ) = get_template_and_user ( } ); -my $patron = Koha::Patrons->find( $borrowernumber ); +my $patron = Koha::Patrons->find($borrowernumber); my $shelfnumber = $query->param('shelfnumber'); -my $format = $query->param('format'); -my $context = $query->param('context'); +my $format = $query->param('format'); +my $context = $query->param('context'); -my $shelf = Koha::Virtualshelves->find( $shelfnumber ); -if ( $shelf and $shelf->can_be_viewed( $borrowernumber ) ) { +my $shelf = Koha::Virtualshelves->find($shelfnumber); +if ( $shelf and $shelf->can_be_viewed($borrowernumber) ) { - if ($shelfnumber && $format) { + if ( $shelfnumber && $format ) { - - my $contents = $shelf->get_contents; + my $contents = $shelf->get_contents; my $marcflavour = C4::Context->preference('marcflavour'); my $output; my $extension; my $type; - # CSV - if ($format =~ /^\d+$/) { + # CSV + if ( $format =~ /^\d+$/ ) { my $csv_profile = Koha::CsvProfiles->find($format); if ( not $csv_profile or $csv_profile->staff_only ) { @@ -82,12 +81,11 @@ if ( $shelf and $shelf->can_be_viewed( $borrowernumber ) ) { while ( my $content = $contents->next ) { push @biblios, $content->biblionumber; } - $output = marc2csv(\@biblios, $format); - # Other formats + $output = marc2csv( \@biblios, $format ); + + # Other formats } else { - my $record_processor = Koha::RecordProcessor->new({ - filters => 'ViewPolicy' - }); + my $record_processor = Koha::RecordProcessor->new( { filters => 'ViewPolicy' } ); while ( my $content = $contents->next ) { my $biblionumber = $content->biblionumber; @@ -99,39 +97,40 @@ if ( $shelf and $shelf->can_be_viewed( $borrowernumber ) ) { patron => $patron, } ); - my $xslFile = $query->param("file"); + my $xslFile = $query->param("file"); my $framework = $biblio->frameworkcode; - $record_processor->options({ - interface => 'opac', - frameworkcode => $framework - }); + $record_processor->options( + { + interface => 'opac', + frameworkcode => $framework + } + ); $record_processor->process($record); next unless $record; - if ($format eq 'iso2709') { + if ( $format eq 'iso2709' ) { $output .= $record->as_usmarc(); - } - elsif ($format eq 'ris' ) { + } elsif ( $format eq 'ris' ) { $output .= marc2ris($record); - } - elsif ($format eq 'bibtex') { - $output .= marc2bibtex($record, $biblionumber); - } - elsif ( $format eq 'isbd' ) { - $output .= GetISBDView({ - 'record' => $record, - 'template' => 'opac', - 'framework' => $framework, - }); + } elsif ( $format eq 'bibtex' ) { + $output .= marc2bibtex( $record, $biblionumber ); + } elsif ( $format eq 'isbd' ) { + $output .= GetISBDView( + { + 'record' => $record, + 'template' => 'opac', + 'framework' => $framework, + } + ); $extension = "txt"; $type = "text/plain"; - }elsif ($format =~ /^xsl\.(.*)$/){ + } elsif ( $format =~ /^xsl\.(.*)$/ ) { $output .= XSLTParse4Display( { biblionumber => $biblionumber, - record => $record, + record => $record, xsl_syspref => "XSLTCustomExport", - fix_amps => 1, + fix_amps => 1, hidden_items => undef, xslfilename => $xslFile, } @@ -141,22 +140,22 @@ if ( $shelf and $shelf->can_be_viewed( $borrowernumber ) ) { } # If it was a CSV export we change the format after the export so the file extension is fine - $format = "csv" if ($format =~ m/^\d+$/); - $format = "html" if ($format =~ /^xsl\./); + $format = "csv" if ( $format =~ m/^\d+$/ ); + $format = "html" if ( $format =~ /^xsl\./ ); print $query->header( - -type => ($type) ? $type : 'application/octet-stream', + -type => ($type) ? $type : 'application/octet-stream', -'Content-Transfer-Encoding' => 'binary', - -attachment => ($extension) ? "shelf.$format.$extension" : "shelf.$format" + -attachment => ($extension) ? "shelf.$format.$extension" : "shelf.$format" ); print $output; } else { # if modal context is passed set a variable so that page markup can be different - if($context eq "modal"){ - $template->param(modal => 1); + if ( $context eq "modal" ) { + $template->param( modal => 1 ); } else { - $template->param(fullpage => 1); + $template->param( fullpage => 1 ); } $template->param( csv_profiles => Koha::CsvProfiles->search( @@ -168,12 +167,12 @@ if ( $shelf and $shelf->can_be_viewed( $borrowernumber ) ) { ), shelf => $shelf, ); - $template->param(xsl_exports => CustomXSLTExportList()); - $template->param( shelf => $shelf ); + $template->param( xsl_exports => CustomXSLTExportList() ); + $template->param( shelf => $shelf ); output_html_with_http_headers $query, $cookie, $template->output; } } else { - $template->param(invalidlist => 1); + $template->param( invalidlist => 1 ); output_html_with_http_headers $query, $cookie, $template->output; } --- a/opac/opac-export.pl +++ a/opac/opac-export.pl @@ -34,10 +34,10 @@ use Koha::Biblios; use C4::XSLT qw( XSLTParse4Display ); use Koha::RecordProcessor; -my $query = CGI->new; -my $op=$query->param("op")||''; #op=export is currently the only use -my $format=$query->param("format")||'utf8'; -my $biblionumber = $query->param("bib")||0; +my $query = CGI->new; +my $op = $query->param("op") || ''; #op=export is currently the only use +my $format = $query->param("format") || 'utf8'; +my $biblionumber = $query->param("bib") || 0; $biblionumber = int($biblionumber); my $error = q{}; @@ -48,151 +48,144 @@ my $patron; if ($userenv) { my $borrowernumber = $userenv->{'number'}; if ($borrowernumber) { - $patron = Koha::Patrons->find( $borrowernumber ); + $patron = Koha::Patrons->find($borrowernumber); } } -my $include_items = ($format =~ /bibtex/) ? 0 : 1; -my $biblio = Koha::Biblios->find($biblionumber); -my $marc = $biblio - ? $biblio->metadata->record( +my $include_items = ( $format =~ /bibtex/ ) ? 0 : 1; +my $biblio = Koha::Biblios->find($biblionumber); +my $marc = $biblio + ? $biblio->metadata->record( { embed_items => 1, opac => 1, patron => $patron, } - ) - : undef; + ) + : undef; -if(!$marc) { +if ( !$marc ) { print $query->redirect("/cgi-bin/koha/errors/404.pl"); exit; } -my $file_id = $biblionumber; +my $file_id = $biblionumber; my $file_pre = "bib-"; -if( C4::Context->preference('DefaultSaveRecordFileID') eq 'controlnumber' ){ - my $marcflavour = C4::Context->preference('marcflavour'); #FIXME This option is required but does not change control num behaviour +if ( C4::Context->preference('DefaultSaveRecordFileID') eq 'controlnumber' ) { + my $marcflavour = + C4::Context->preference('marcflavour'); #FIXME This option is required but does not change control num behaviour my $control_num = GetMarcControlnumber( $marc, $marcflavour ); - if( $control_num ){ - $file_id = $control_num; + if ($control_num) { + $file_id = $control_num; $file_pre = "record-"; } } -my $framework = $biblio->frameworkcode; -my $record_processor = Koha::RecordProcessor->new({ - filters => 'ViewPolicy', - options => { - interface => 'opac', - frameworkcode => $framework +my $framework = $biblio->frameworkcode; +my $record_processor = Koha::RecordProcessor->new( + { + filters => 'ViewPolicy', + options => { + interface => 'opac', + frameworkcode => $framework + } } -}); +); $record_processor->process($marc); -if ($format =~ /endnote/) { - $marc = marc2endnote($marc); +if ( $format =~ /endnote/ ) { + $marc = marc2endnote($marc); $format = 'endnote'; -} -elsif ($format =~ /marcxml/) { - $marc = marc2marcxml($marc); +} elsif ( $format =~ /marcxml/ ) { + $marc = marc2marcxml($marc); $format = 'marcxml'; -} -elsif ($format=~ /mods/) { - $marc = marc2modsxml($marc); +} elsif ( $format =~ /mods/ ) { + $marc = marc2modsxml($marc); $format = 'mods'; -} -elsif ($format =~ /ris/) { - $marc = marc2ris($marc); +} elsif ( $format =~ /ris/ ) { + $marc = marc2ris($marc); $format = 'ris'; -} -elsif ($format =~ /bibtex/) { - $marc = marc2bibtex($marc,$biblionumber); +} elsif ( $format =~ /bibtex/ ) { + $marc = marc2bibtex( $marc, $biblionumber ); $format = 'bibtex'; -} -elsif ($format =~ /^(dc|oaidc|srwdc|rdfdc)$/i ) { +} elsif ( $format =~ /^(dc|oaidc|srwdc|rdfdc)$/i ) { + # TODO: Dublin Core leaks fields marked hidden by framework. - $marc = marc2dcxml($marc, undef, $biblionumber, $format); + $marc = marc2dcxml( $marc, undef, $biblionumber, $format ); $format = "dublin-core.xml"; -} -elsif ($format =~ /marc8/) { - ($error,$marc) = changeEncoding($marc,"MARC","MARC21","MARC-8"); - $marc = $marc->as_usmarc() unless $error; +} elsif ( $format =~ /marc8/ ) { + ( $error, $marc ) = changeEncoding( $marc, "MARC", "MARC21", "MARC-8" ); + $marc = $marc->as_usmarc() unless $error; $format = 'marc8'; -} -elsif ($format =~ /utf8/) { - C4::Charset::SetUTF8Flag($marc,1); - $marc = $marc->as_usmarc(); +} elsif ( $format =~ /utf8/ ) { + C4::Charset::SetUTF8Flag( $marc, 1 ); + $marc = $marc->as_usmarc(); $format = 'utf8'; -} -elsif ($format =~ /marcstd/) { - C4::Charset::SetUTF8Flag($marc,1); - ($error,$marc) = marc2marc($marc, 'marcstd', C4::Context->preference('marcflavour')); +} elsif ( $format =~ /marcstd/ ) { + C4::Charset::SetUTF8Flag( $marc, 1 ); + ( $error, $marc ) = marc2marc( $marc, 'marcstd', C4::Context->preference('marcflavour') ); $format = 'marcstd'; -} -elsif ( $format =~ /isbd/ ) { - $marc = GetISBDView({ - 'record' => $marc, - 'template' => 'opac', - 'framework' => $framework, - }); +} elsif ( $format =~ /isbd/ ) { + $marc = GetISBDView( + { + 'record' => $marc, + 'template' => 'opac', + 'framework' => $framework, + } + ); $format = 'isbd'; -} -elsif ($format =~ /html/ ) { - if ($biblionumber){ +} elsif ( $format =~ /html/ ) { + if ($biblionumber) { my $xslFile = $query->param("file"); - my $biblio = Koha::Biblios->find($biblionumber); + my $biblio = Koha::Biblios->find($biblionumber); $marc = $biblio->metadata->record; my @hiddenitems; $marc = XSLTParse4Display( { biblionumber => $biblionumber, - record => $marc, + record => $marc, xsl_syspref => "OPACXSLTCustomExport", - fix_amps => 1, + fix_amps => 1, hidden_items => \@hiddenitems, - xslfilename => $xslFile, + xslfilename => $xslFile, } ); } -} -else { - $error= "Format $format is not supported."; +} else { + $error = "Format $format is not supported."; } -if ($error){ +if ($error) { print $query->header(); print $query->start_html(); print "

    An error occurred

    "; print $query->escapeHTML("$error"); print $query->end_html(); -} -else { - if ($format eq 'marc8'){ +} else { + if ( $format eq 'marc8' ) { print $query->header( - -type => 'application/marc', - -charset=>'ISO-2022', - -attachment=>"$file_pre$file_id.$format"); - } - elsif ( $format eq 'isbd' ) { + -type => 'application/marc', + -charset => 'ISO-2022', + -attachment => "$file_pre$file_id.$format" + ); + } elsif ( $format eq 'isbd' ) { print $query->header( -type => 'text/plain', -charset => 'utf-8', - -attachment => "$file_pre$file_id.txt" + -attachment => "$file_pre$file_id.txt" ); - } - elsif ( $format eq 'ris' ) { + } elsif ( $format eq 'ris' ) { print $query->header( - -type => 'text/plain', - -charset => 'utf-8', + -type => 'text/plain', + -charset => 'utf-8', -attachment => "$file_pre$file_id.$format" ); } else { binmode STDOUT, ':encoding(UTF-8)'; print $query->header( - -type => 'application/octet-stream', - -charset => 'utf-8', + -type => 'application/octet-stream', + -charset => 'utf-8', -attachment => "$file_pre$file_id.$format" ); } --- a/opac/opac-shelves.pl +++ a/opac/opac-shelves.pl @@ -46,8 +46,8 @@ use Koha::Virtualshelfshares; use Koha::Virtualshelves; use Koha::RecordProcessor; -use constant ANYONE => 2; -use constant STAFF => 3; +use constant ANYONE => 2; +use constant STAFF => 3; use constant PERMITTED => 4; my $query = CGI->new; @@ -55,7 +55,7 @@ my $query = CGI->new; my $template_name = $query->param('rss') ? "opac-shelves-rss.tt" : "opac-shelves.tt"; # if virtualshelves is disabled, leave immediately -if ( ! C4::Context->preference('virtualshelves') ) { +if ( !C4::Context->preference('virtualshelves') ) { print $query->redirect("/cgi-bin/koha/errors/404.pl"); exit; } @@ -63,48 +63,53 @@ if ( ! C4::Context->preference('virtualshelves') ) { my $op = $query->param('op') || 'list'; my ( $template, $loggedinuser, $cookie ); -if( $op eq 'view' || $op eq 'list' ){ - ( $template, $loggedinuser, $cookie ) = get_template_and_user({ +if ( $op eq 'view' || $op eq 'list' ) { + ( $template, $loggedinuser, $cookie ) = get_template_and_user( + { template_name => $template_name, query => $query, type => "opac", authnotrequired => ( C4::Context->preference("OpacPublic") ? 1 : 0 ), - }); + } + ); } else { - ( $template, $loggedinuser, $cookie ) = get_template_and_user({ + ( $template, $loggedinuser, $cookie ) = get_template_and_user( + { template_name => $template_name, query => $query, type => "opac", authnotrequired => 0, - }); + } + ); } -if (C4::Context->preference("BakerTaylorEnabled")) { +if ( C4::Context->preference("BakerTaylorEnabled") ) { $template->param( BakerTaylorImageURL => &image_url(), BakerTaylorLinkURL => &link_url(), ); } -my $referer = $query->param('referer') || $op; -my $public = 0; +my $referer = $query->param('referer') || $op; +my $public = 0; $public = 1 if $query->param('public') && $query->param('public') == 1; my ( $shelf, $shelfnumber, @messages ); # PART 1: Perform a few actions if ( $op eq 'add_form' ) { + # Only pass default $shelf = { allow_change_from_owner => 1 }; } elsif ( $op eq 'edit_form' ) { $shelfnumber = $query->param('shelfnumber'); $shelf = Koha::Virtualshelves->find($shelfnumber); - if ( $shelf ) { + if ($shelf) { $public = $shelf->public; my $patron = Koha::Patrons->find( $shelf->owner ); $template->param( owner => $patron, ); - unless ( $shelf->can_be_managed( $loggedinuser ) ) { + unless ( $shelf->can_be_managed($loggedinuser) ) { push @messages, { type => 'error', code => 'unauthorized_on_update' }; $op = 'list'; } @@ -112,18 +117,19 @@ if ( $op eq 'add_form' ) { push @messages, { type => 'error', code => 'does_not_exist' }; } } elsif ( $op eq 'add' ) { - if ( $loggedinuser ) { + if ($loggedinuser) { my $allow_changes_from = $query->param('allow_changes_from'); eval { $shelf = Koha::Virtualshelf->new( - { shelfname => scalar $query->param('shelfname'), - sortfield => scalar $query->param('sortfield'), - public => $public, - allow_change_from_owner => $allow_changes_from > 0, - allow_change_from_others => $allow_changes_from == ANYONE, - allow_change_from_staff => $allow_changes_from == STAFF, + { + shelfname => scalar $query->param('shelfname'), + sortfield => scalar $query->param('sortfield'), + public => $public, + allow_change_from_owner => $allow_changes_from > 0, + allow_change_from_others => $allow_changes_from == ANYONE, + allow_change_from_staff => $allow_changes_from == STAFF, allow_change_from_permitted_staff => $allow_changes_from == PERMITTED, - owner => scalar $loggedinuser, + owner => scalar $loggedinuser, } ); $shelf->store; @@ -144,19 +150,19 @@ if ( $op eq 'add_form' ) { } elsif ( $op eq 'edit' ) { $shelfnumber = $query->param('shelfnumber'); $shelf = Koha::Virtualshelves->find($shelfnumber); - if ( $shelf ) { + if ($shelf) { $op = $referer; my $sortfield = $query->param('sortfield'); $sortfield = 'title' unless grep { $_ eq $sortfield } qw( title author copyrightdate itemcallnumber dateadded ); - if ( $shelf->can_be_managed( $loggedinuser ) ) { + if ( $shelf->can_be_managed($loggedinuser) ) { $shelf->shelfname( scalar $query->param('shelfname') ); - $shelf->sortfield( $sortfield ); + $shelf->sortfield($sortfield); my $allow_changes_from = $query->param('allow_changes_from'); $shelf->allow_change_from_owner( $allow_changes_from > 0 ); $shelf->allow_change_from_others( $allow_changes_from == ANYONE ); $shelf->allow_change_from_staff( $allow_changes_from == STAFF ); $shelf->allow_change_from_permitted_staff( $allow_changes_from == PERMITTED ); - $shelf->public( $public ); + $shelf->public($public); eval { $shelf->store }; if ($@) { @@ -175,7 +181,7 @@ if ( $op eq 'add_form' ) { $shelfnumber = $query->param('shelfnumber'); $shelf = Koha::Virtualshelves->find($shelfnumber); if ($shelf) { - if ( $shelf->can_be_deleted( $loggedinuser ) ) { + if ( $shelf->can_be_deleted($loggedinuser) ) { eval { $shelf->delete; }; if ($@) { push @messages, { type => 'error', code => ref($@), msg => $@ }; @@ -191,12 +197,12 @@ if ( $op eq 'add_form' ) { $op = $referer; } elsif ( $op eq 'remove_share' ) { $shelfnumber = $query->param('shelfnumber'); - $shelf = Koha::Virtualshelves->find($shelfnumber); + $shelf = Koha::Virtualshelves->find($shelfnumber); if ($shelf) { - my $removed = eval { $shelf->remove_share( $loggedinuser ); }; + my $removed = eval { $shelf->remove_share($loggedinuser); }; if ($@) { push @messages, { type => 'error', code => ref($@), msg => $@ }; - } elsif ( $removed ) { + } elsif ($removed) { push @messages, { type => 'message', code => 'success_on_remove_share' }; } else { push @messages, { type => 'error', code => 'error_on_remove_share' }; @@ -208,16 +214,16 @@ if ( $op eq 'add_form' ) { } elsif ( $op eq 'add_biblio' ) { $shelfnumber = $query->param('shelfnumber'); - $shelf = Koha::Virtualshelves->find($shelfnumber); + $shelf = Koha::Virtualshelves->find($shelfnumber); if ($shelf) { - if( my $barcode = $query->param('barcode') ) { - my $item = Koha::Items->find({ barcode => $barcode }); - if ( $item ) { - if ( $shelf->can_biblios_be_added( $loggedinuser ) ) { + if ( my $barcode = $query->param('barcode') ) { + my $item = Koha::Items->find( { barcode => $barcode } ); + if ($item) { + if ( $shelf->can_biblios_be_added($loggedinuser) ) { my $added = eval { $shelf->add_biblio( $item->biblionumber, $loggedinuser ); }; if ($@) { push @messages, { type => 'error', code => ref($@), msg => $@ }; - } elsif ( $added ) { + } elsif ($added) { push @messages, { type => 'message', code => 'success_on_add_biblio' }; } else { push @messages, { type => 'message', code => 'error_on_add_biblio' }; @@ -235,21 +241,21 @@ if ( $op eq 'add_form' ) { $op = $referer; } elsif ( $op eq 'remove_biblios' ) { $shelfnumber = $query->param('shelfnumber'); - $shelf = Koha::Virtualshelves->find($shelfnumber); + $shelf = Koha::Virtualshelves->find($shelfnumber); my @biblionumber = $query->multi_param('biblionumber'); if ($shelf) { - if ( $shelf->can_biblios_be_removed( $loggedinuser ) ) { + if ( $shelf->can_biblios_be_removed($loggedinuser) ) { my $number_of_biblios_removed = eval { $shelf->remove_biblios( { - biblionumbers => \@biblionumber, + biblionumbers => \@biblionumber, borrowernumber => $loggedinuser, } ); }; if ($@) { push @messages, { type => 'error', code => ref($@), msg => $@ }; - } elsif ( $number_of_biblios_removed ) { + } elsif ($number_of_biblios_removed) { push @messages, { type => 'message', code => 'success_on_remove_biblios' }; } else { push @messages, { type => 'error', code => 'no_biblio_removed' }; @@ -261,36 +267,41 @@ if ( $op eq 'add_form' ) { push @messages, { type => 'error', code => 'does_not_exist' }; } $op = 'view'; -} elsif( $op eq 'transfer' ) { +} elsif ( $op eq 'transfer' ) { $shelfnumber = $query->param('shelfnumber'); - $shelf = Koha::Virtualshelves->find($shelfnumber) if $shelfnumber; - my $new_owner = $query->param('new_owner'); # borrowernumber or undef - my $error_code = $shelf - ? $shelf->cannot_be_transferred({ by => $loggedinuser, to => $new_owner, interface => 'opac' }) + $shelf = Koha::Virtualshelves->find($shelfnumber) if $shelfnumber; + my $new_owner = $query->param('new_owner'); # borrowernumber or undef + my $error_code = + $shelf + ? $shelf->cannot_be_transferred( { by => $loggedinuser, to => $new_owner, interface => 'opac' } ) : 'does_not_exist'; - if( !$new_owner && $error_code eq 'missing_to_parameter' ) { # show transfer form + if ( !$new_owner && $error_code eq 'missing_to_parameter' ) { # show transfer form my $patrons = []; - my $shares = $shelf->get_shares->search({ borrowernumber => { '!=' => undef } }); - while( my $share = $shares->next ) { + my $shares = $shelf->get_shares->search( { borrowernumber => { '!=' => undef } } ); + while ( my $share = $shares->next ) { my $email = $share->sharee->notice_email_address; push @$patrons, { email => $email, borrowernumber => $share->get_column('borrowernumber') } if $email; } - if( @$patrons ) { + if (@$patrons) { $template->param( shared_users => $patrons ); $op = 'transfer'; } else { push @messages, { type => 'error', code => 'no_email_found' }; } - } elsif( $error_code ) { + } elsif ($error_code) { push @messages, { type => 'error', code => $error_code }; $op = 'list'; - } else { # transfer; remove new_owner from virtualshelfshares, add loggedinuser - $shelf->_result->result_source->schema->txn_do( sub { - $shelf->get_shares->search({ borrowernumber => $new_owner })->delete; - Koha::Virtualshelfshare->new({ shelfnumber => $shelfnumber, borrowernumber => $loggedinuser, sharedate => dt_from_string })->store; - $shelf->owner($new_owner)->store; - }); + } else { # transfer; remove new_owner from virtualshelfshares, add loggedinuser + $shelf->_result->result_source->schema->txn_do( + sub { + $shelf->get_shares->search( { borrowernumber => $new_owner } )->delete; + Koha::Virtualshelfshare->new( + { shelfnumber => $shelfnumber, borrowernumber => $loggedinuser, sharedate => dt_from_string } ) + ->store; + $shelf->owner($new_owner)->store; + } + ); $op = 'list'; } } @@ -299,21 +310,23 @@ if ( $op eq 'add_form' ) { if ( $op eq 'view' ) { $shelfnumber ||= $query->param('shelfnumber'); $shelf = Koha::Virtualshelves->find($shelfnumber); - if ( $shelf ) { - if ( $shelf->can_be_viewed( $loggedinuser ) ) { + if ($shelf) { + if ( $shelf->can_be_viewed($loggedinuser) ) { $public = $shelf->public; # Sortfield param may still include sort order with :asc or :desc, but direction overrides it - my( $sortfield, $direction ); - if( $query->param('sortfield') ){ + my ( $sortfield, $direction ); + if ( $query->param('sortfield') ) { ( $sortfield, $direction ) = split /:/, $query->param('sortfield'); } else { $sortfield = $shelf->sortfield; $direction = 'asc'; } $direction = $query->param('direction') if $query->param('direction'); - $direction = 'asc' if !$direction or ( $direction ne 'asc' and $direction ne 'desc' ); - $sortfield = 'title' if !$sortfield or !grep { $_ eq $sortfield } qw( title author copyrightdate itemcallnumber dateadded ); + $direction = 'asc' if !$direction or ( $direction ne 'asc' and $direction ne 'desc' ); + $sortfield = 'title' + if !$sortfield + or !grep { $_ eq $sortfield } qw( title author copyrightdate itemcallnumber dateadded ); my ( $page, $rows ); unless ( $query->param('print') or $query->param('rss') ) { @@ -334,22 +347,23 @@ if ( $op eq 'view' ) { # get biblionumbers stored in the cart my @cart_list; - if(my $cart_list = $query->cookie('bib_list')){ - @cart_list = split(/\//, $cart_list); + if ( my $cart_list = $query->cookie('bib_list') ) { + @cart_list = split( /\//, $cart_list ); } - my $patron = Koha::Patrons->find( $loggedinuser ); + my $patron = Koha::Patrons->find($loggedinuser); - my $categorycode; # needed for may_article_request - if( C4::Context->preference('ArticleRequests') ) { + my $categorycode; # needed for may_article_request + if ( C4::Context->preference('ArticleRequests') ) { $categorycode = $patron ? $patron->categorycode : undef; } - my $record_processor = Koha::RecordProcessor->new({ filters => 'ViewPolicy' }); + my $record_processor = Koha::RecordProcessor->new( { filters => 'ViewPolicy' } ); my $art_req_itypes; - if( C4::Context->preference('ArticleRequests') ) { - $art_req_itypes = Koha::CirculationRules->guess_article_requestable_itemtypes({ $patron ? ( categorycode => $patron->categorycode ) : () }); + if ( C4::Context->preference('ArticleRequests') ) { + $art_req_itypes = Koha::CirculationRules->guess_article_requestable_itemtypes( + { $patron ? ( categorycode => $patron->categorycode ) : () } ); } my @items_info; @@ -361,26 +375,29 @@ if ( $op eq 'view' ) { my $framework = GetFrameworkCode($biblionumber); $record_processor->options( { - interface => 'opac', - frameworkcode => $framework - }); + interface => 'opac', + frameworkcode => $framework + } + ); $record_processor->process($record); my $marcflavour = C4::Context->preference("marcflavour"); - my $itemtype = Koha::Biblioitems->search({ biblionumber => $content->biblionumber })->next->itemtype; - $itemtype = Koha::ItemTypes->find( $itemtype ); - if( $itemtype ) { - $this_item->{imageurl} = C4::Koha::getitemtypeimagelocation( 'opac', $itemtype->imageurl ); - $this_item->{description} = $itemtype->description; #FIXME Should not it be translated_description? - $this_item->{notforloan} = $itemtype->notforloan; + my $itemtype = Koha::Biblioitems->search( { biblionumber => $content->biblionumber } )->next->itemtype; + $itemtype = Koha::ItemTypes->find($itemtype); + if ($itemtype) { + $this_item->{imageurl} = C4::Koha::getitemtypeimagelocation( 'opac', $itemtype->imageurl ); + $this_item->{description} = $itemtype->description; #FIXME Should not it be translated_description? + $this_item->{notforloan} = $itemtype->notforloan; } $this_item->{'coins'} = $biblio->get_coins; $this_item->{'normalized_upc'} = GetNormalizedUPC( $record, $marcflavour ); $this_item->{'normalized_ean'} = GetNormalizedEAN( $record, $marcflavour ); $this_item->{'normalized_oclc'} = GetNormalizedOCLCNumber( $record, $marcflavour ); $this_item->{'normalized_isbn'} = GetNormalizedISBN( undef, $record, $marcflavour ); + # BZ17530: 'Intelligent' guess if result can be article requested - $this_item->{artreqpossible} = ( $art_req_itypes->{ $this_item->{itemtype} // q{} } || $art_req_itypes->{ '*' } ) ? 1 : q{}; + $this_item->{artreqpossible} = + ( $art_req_itypes->{ $this_item->{itemtype} // q{} } || $art_req_itypes->{'*'} ) ? 1 : q{}; unless ( defined $this_item->{size} ) { @@ -388,29 +405,29 @@ if ( $op eq 'view' ) { $this_item->{size} = q||; } - if (C4::Context->preference('TagsEnabled') and C4::Context->preference('TagsShowOnList')) { - $this_item->{TagLoop} = get_tags({ - biblionumber => $biblionumber, approved=>1, 'sort'=>'-weight', - limit => C4::Context->preference('TagsShowOnList'), - }); + if ( C4::Context->preference('TagsEnabled') and C4::Context->preference('TagsShowOnList') ) { + $this_item->{TagLoop} = get_tags( + { + biblionumber => $biblionumber, approved => 1, 'sort' => '-weight', + limit => C4::Context->preference('TagsShowOnList'), + } + ); } - my $items = $biblio->items->filter_by_visible_in_opac({ patron => $patron }); + my $items = $biblio->items->filter_by_visible_in_opac( { patron => $patron } ); my $allow_onshelf_holds; while ( my $item = $items->next ) { # This method must take a Koha::Items rs - $allow_onshelf_holds ||= Koha::CirculationRules->get_onshelfholds_policy( - { item => $item, patron => $patron } ); + $allow_onshelf_holds ||= + Koha::CirculationRules->get_onshelfholds_policy( { item => $item, patron => $patron } ); } $this_item->{allow_onshelf_holds} = $allow_onshelf_holds; - $this_item->{'ITEM_RESULTS'} = $items; + $this_item->{'ITEM_RESULTS'} = $items; - my $variables = { - anonymous_session => ($loggedinuser) ? 0 : 1 - }; + my $variables = { anonymous_session => ($loggedinuser) ? 0 : 1 }; $this_item->{XSLTBloc} = XSLTParse4Display( { biblionumber => $biblionumber, @@ -422,20 +439,18 @@ if ( $op eq 'view' ) { } ); - - if ( grep {$_ eq $biblionumber} @cart_list) { + if ( grep { $_ eq $biblionumber } @cart_list ) { $this_item->{incart} = 1; } $this_item->{biblio_object} = $biblio; $this_item->{biblionumber} = $biblionumber; - $this_item->{shelves} = - Koha::Virtualshelves->get_shelves_containing_record( + $this_item->{shelves} = Koha::Virtualshelves->get_shelves_containing_record( { biblionumber => $biblionumber, borrowernumber => $loggedinuser, } - ); + ); push @items_info, $this_item; } @@ -447,20 +462,24 @@ if ( $op eq 'view' ) { itemsloop => \@items_info, sortfield => $sortfield, direction => $direction, - csv_profiles => Koha::CsvProfiles->search( + csv_profiles => Koha::CsvProfiles->search( { type => 'marc', used_for => 'export_records', staff_only => 0 } - ), + ), ); - if ( $page ) { + if ($page) { my $pager = $contents->pager; $template->param( pagination_bar => pagination_bar( - q||, $pager->last_page - $pager->first_page + 1, - $page, "page", { op => 'view', shelfnumber => $shelf->shelfnumber, sortfield => $sortfield, direction => $direction, } + q||, $pager->last_page - $pager->first_page + 1, + $page, "page", + { + op => 'view', shelfnumber => $shelf->shelfnumber, sortfield => $sortfield, + direction => $direction, + } ), ); } @@ -475,24 +494,25 @@ if ( $op eq 'view' ) { my $shelves; my ( $page, $rows ) = ( $query->param('page') || 1, 20 ); if ( !$public ) { - $shelves = Koha::Virtualshelves->get_private_shelves({ page => $page, rows => $rows, borrowernumber => $loggedinuser, }); + $shelves = Koha::Virtualshelves->get_private_shelves( + { page => $page, rows => $rows, borrowernumber => $loggedinuser, } ); } else { - $shelves = Koha::Virtualshelves->get_public_shelves({ page => $page, rows => $rows, }); + $shelves = Koha::Virtualshelves->get_public_shelves( { page => $page, rows => $rows, } ); } my $pager = $shelves->pager; $template->param( - shelves => $shelves, + shelves => $shelves, pagination_bar => pagination_bar( - q||, $pager->last_page - $pager->first_page + 1, + q||, $pager->last_page - $pager->first_page + 1, $page, "page", { op => 'list', public => $public, } ), ); } -my ($staffuser, $permitteduser); -$staffuser = Koha::Patrons->find( $loggedinuser )->can_patron_change_staff_only_lists if $loggedinuser; -$permitteduser = Koha::Patrons->find( $loggedinuser )->can_patron_change_permitted_staff_lists if $loggedinuser; +my ( $staffuser, $permitteduser ); +$staffuser = Koha::Patrons->find($loggedinuser)->can_patron_change_staff_only_lists if $loggedinuser; +$permitteduser = Koha::Patrons->find($loggedinuser)->can_patron_change_permitted_staff_lists if $loggedinuser; $template->param( op => $op, @@ -504,8 +524,8 @@ $template->param( listsview => 1, staffuser => $staffuser, permitteduser => $permitteduser, - xsl_exports => CustomXSLTExportList() + xsl_exports => CustomXSLTExportList() ); -my $content_type = $query->param('rss')? 'rss' : 'html'; +my $content_type = $query->param('rss') ? 'rss' : 'html'; output_with_http_headers $query, $cookie, $template->output, $content_type; --- a/t/db_dependent/XSLT.t +++ a/t/db_dependent/XSLT.t @@ -30,7 +30,7 @@ use Koha::Libraries; use Koha::ItemTypes; BEGIN { - use_ok('C4::XSLT', qw( buildKohaItemsNamespace )); + use_ok( 'C4::XSLT', qw( buildKohaItemsNamespace ) ); } my $schema = Koha::Database->new->schema; @@ -38,12 +38,12 @@ my $builder = t::lib::TestBuilder->new; our $cache = Koha::Caches->get_instance; subtest 'Tests moved from t' => sub { - plan tests => 11; + plan tests => 14; $schema->storage->txn_begin; - my $dir = File::Temp->newdir(); - my @themes = ('prog', 'test'); - my @langs = ('en', 'es-ES'); + my $dir = File::Temp->newdir(); + my @themes = ( 'prog', 'test' ); + my @langs = ( 'en', 'es-ES' ); # create temporary files to be tested later foreach my $theme (@themes) { @@ -56,9 +56,9 @@ subtest 'Tests moved from t' => sub { } sub find_and_slurp { - my ($dir, $theme, $lang) = @_; + my ( $dir, $theme, $lang ) = @_; - my $filename = C4::XSLT::_get_best_default_xslt_filename($dir, $theme, $lang, 'my_file.xslt'); + my $filename = C4::XSLT::_get_best_default_xslt_filename( $dir, $theme, $lang, 'my_file.xslt' ); open my $fh, '<', $filename; my $str = <$fh>; close $fh; @@ -67,49 +67,69 @@ subtest 'Tests moved from t' => sub { # These tests verify that we're finding the right XSLT file when present, # and falling back to the right XSLT file when an exact match is not present. - is(find_and_slurp($dir, 'test', 'en' ), 'Theme test, language en', 'Found test/en'); - is(find_and_slurp($dir, 'test', 'es-ES'), 'Theme test, language es-ES', 'Found test/es-ES'); - is(find_and_slurp($dir, 'prog', 'en', ), 'Theme prog, language en', 'Found test/en'); - is(find_and_slurp($dir, 'prog', 'es-ES'), 'Theme prog, language es-ES', 'Found test/es-ES'); - is(find_and_slurp($dir, 'test', 'fr-FR'), 'Theme test, language en', 'Fell back to test/en for test/fr-FR'); - is(find_and_slurp($dir, 'nope', 'es-ES'), 'Theme prog, language es-ES', 'Fell back to prog/es-ES for nope/es-ES'); - is(find_and_slurp($dir, 'nope', 'fr-FR'), 'Theme prog, language en', 'Fell back to prog/en for nope/fr-FR'); + is( find_and_slurp( $dir, 'test', 'en' ), 'Theme test, language en', 'Found test/en' ); + is( find_and_slurp( $dir, 'test', 'es-ES' ), 'Theme test, language es-ES', 'Found test/es-ES' ); + is( find_and_slurp( $dir, 'prog', 'en', ), 'Theme prog, language en', 'Found test/en' ); + is( find_and_slurp( $dir, 'prog', 'es-ES' ), 'Theme prog, language es-ES', 'Found test/es-ES' ); + is( find_and_slurp( $dir, 'test', 'fr-FR' ), 'Theme test, language en', 'Fell back to test/en for test/fr-FR' ); + is( + find_and_slurp( $dir, 'nope', 'es-ES' ), 'Theme prog, language es-ES', + 'Fell back to prog/es-ES for nope/es-ES' + ); + is( find_and_slurp( $dir, 'nope', 'fr-FR' ), 'Theme prog, language en', 'Fell back to prog/en for nope/fr-FR' ); my $matching_string = q{[0|1]}; - my $sysprefs_xml = C4::XSLT::get_xslt_sysprefs(); - ok( $sysprefs_xml =~ m/$matching_string/, 'singleBranchMode has no value'); + my $sysprefs_xml = C4::XSLT::get_xslt_sysprefs(); + ok( $sysprefs_xml =~ m/$matching_string/, 'singleBranchMode has no value' ); + + sub createXSLTFiles { + my ( $path ) = @_; + + open my $fh, '>', "$path/export_01.xsl"; + print $fh qq| + + |; + close $fh; + + # Make XSL without title + open $fh, '>', "$path/export_02.xsl"; + print $fh qq| + + |; + close $fh; + + open $fh, '>', "$path/export_03.xsl"; + print $fh qq||; + close $fh; + } + + t::lib::Mocks::mock_preference( 'CustomXSLTExportPath', '' ); + t::lib::Mocks::mock_config( 'opachtdocs', "$dir" ); - t::lib::Mocks::mock_config('opachtdocs', "$dir"); make_path("$dir/bootstrap/en/xslt/biblioexport"); + createXSLTFiles("$dir/bootstrap/en/xslt/biblioexport"); - # Make XSL with title - open my $fh, '>', "$dir/bootstrap/en/xslt/biblioexport/export_01.xsl"; - print $fh qq| - - |; - close $fh; - - # Make XSL without title - open $fh, '>', "$dir/bootstrap/en/xslt/biblioexport/export_02.xsl"; - print $fh qq| - - |; - close $fh; - - open $fh, '>', "$dir/bootstrap/en/xslt/biblioexport/export_03.xsl"; - print $fh qq||; - close $fh; - - t::lib::Mocks::mock_preference( 'OpacExportOptions', 'custom'); - my @custom_xslts = @{C4::XSLT::CustomXSLTExportList(1)}; - ok((scalar @custom_xslts) == 2, "CustomXSLTExportList finds custom XSLTs"); - ok($custom_xslts[0]->{filename} eq "Export 01", "Title is specified in root node"); - ok($custom_xslts[1]->{filename} eq "export_02", "Title is filename if not specified"); + t::lib::Mocks::mock_preference( 'OpacExportOptions', 'custom' ); + my @custom_xslts = @{ C4::XSLT::CustomXSLTExportList(1) }; + + ok( ( scalar @custom_xslts ) == 2, "CustomXSLTExportList finds custom XSLTs" ); + ok( $custom_xslts[0]->{filename} eq "Export 01", "Title is specified in root node" ); + ok( $custom_xslts[1]->{filename} eq "export_02", "Title is filename if not specified" ); + + # CustomXSLTExportPath + t::lib::Mocks::mock_preference( 'CustomXSLTExportPath', "/$dir/XSLTExportFiles" ); + make_path("$dir/XSLTExportFiles"); + createXSLTFiles("$dir/XSLTExportFiles"); + @custom_xslts = @{ C4::XSLT::CustomXSLTExportList(1) }; + + ok( ( scalar @custom_xslts ) == 2, "CustomXSLTExportList finds custom XSLTs with CustomXSLTExportPath" ); + ok( $custom_xslts[0]->{filename} eq "Export 01", "Title is specified in root node with CustomXSLTExportPath" ); + ok( $custom_xslts[1]->{filename} eq "export_02", "Title is filename if not specified with CustomXSLTExportPath" ); $schema->storage->txn_rollback; }; @@ -118,103 +138,108 @@ subtest 'buildKohaItemsNamespace status tests' => sub { plan tests => 18; $schema->storage->txn_begin; - t::lib::Mocks::mock_preference('Reference_NFL_Statuses', '1|2'); - t::lib::Mocks::mock_preference( 'OPACResultsLibrary', 'holdingbranch' ); - t::lib::Mocks::mock_preference( 'OPACResultsMaxItems', '2' ); + t::lib::Mocks::mock_preference( 'Reference_NFL_Statuses', '1|2' ); + t::lib::Mocks::mock_preference( 'OPACResultsLibrary', 'holdingbranch' ); + t::lib::Mocks::mock_preference( 'OPACResultsMaxItems', '2' ); - my $itype = $builder->build_object({ class => 'Koha::ItemTypes' }); - my $itemtype = $builder->build_object({ class => 'Koha::ItemTypes' }); - my $holdinglibrary = $builder->build_object({ class => 'Koha::Libraries' }); - my $item = $builder->build_sample_item({ itype => $itype->itemtype }); + my $itype = $builder->build_object( { class => 'Koha::ItemTypes' } ); + my $itemtype = $builder->build_object( { class => 'Koha::ItemTypes' } ); + my $holdinglibrary = $builder->build_object( { class => 'Koha::Libraries' } ); + my $item = $builder->build_sample_item( { itype => $itype->itemtype } ); $item->holdingbranch( $holdinglibrary->branchcode )->store; - $item->biblioitem->itemtype($itemtype->itemtype)->store; + $item->biblioitem->itemtype( $itemtype->itemtype )->store; - my $xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber,[]); - like($xml,qr{available},"Item is available when no other status applied"); + my $xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber, [] ); + like( $xml, qr{available}, "Item is available when no other status applied" ); # notforloan { - t::lib::Mocks::mock_preference('item-level_itypes', 0); + t::lib::Mocks::mock_preference( 'item-level_itypes', 0 ); $item->notforloan(0)->store; - Koha::ItemTypes->find($item->itype)->notforloan(0)->store; - Koha::ItemTypes->find($item->biblioitem->itemtype)->notforloan(1)->store; - $xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber,[]); - like($xml,qr{reference},"reference if positive itype notforloan value"); - - t::lib::Mocks::mock_preference('item-level_itypes', 1); - Koha::ItemTypes->find($item->itype)->notforloan(1)->store; - Koha::ItemTypes->find($item->biblioitem->itemtype)->notforloan(0)->store; - $xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber,[]); - like($xml,qr{reference},"reference if positive itemtype notforloan value"); - Koha::ItemTypes->find($item->itype)->notforloan(0)->store; - - my $substatus = Koha::AuthorisedValues->search({ category => 'NOT_LOAN', authorised_value => -1 })->next->lib; + Koha::ItemTypes->find( $item->itype )->notforloan(0)->store; + Koha::ItemTypes->find( $item->biblioitem->itemtype )->notforloan(1)->store; + $xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber, [] ); + like( $xml, qr{reference}, "reference if positive itype notforloan value" ); + + t::lib::Mocks::mock_preference( 'item-level_itypes', 1 ); + Koha::ItemTypes->find( $item->itype )->notforloan(1)->store; + Koha::ItemTypes->find( $item->biblioitem->itemtype )->notforloan(0)->store; + $xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber, [] ); + like( $xml, qr{reference}, "reference if positive itemtype notforloan value" ); + Koha::ItemTypes->find( $item->itype )->notforloan(0)->store; + + my $substatus = Koha::AuthorisedValues->search( { category => 'NOT_LOAN', authorised_value => -1 } )->next->lib; $item->notforloan(-1)->store; - $xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber,[]); - like($xml,qr{reallynotforloan},"reallynotforloan if negative notforloan value"); - like($xml,qr{$substatus},"substatus set if negative notforloan value"); + $xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber, [] ); + like( $xml, qr{reallynotforloan}, "reallynotforloan if negative notforloan value" ); + like( $xml, qr{$substatus}, "substatus set if negative notforloan value" ); $item->notforloan(1)->store; - $xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber,[]); - like($xml,qr{reference},"reference if positive notforloan value"); + $xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber, [] ); + like( $xml, qr{reference}, "reference if positive notforloan value" ); # But now make status notforloan==1 count under Not available - t::lib::Mocks::mock_preference('Reference_NFL_Statuses', '2'); - $xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber,[]); - like($xml,qr{reallynotforloan},"reallynotforloan when we change Reference_NFL_Statuses"); - t::lib::Mocks::mock_preference('Reference_NFL_Statuses', q{}); # empty, same effect - $xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber,[]); - like($xml,qr{reallynotforloan},"reallynotforloan when we empty Reference_NFL_Statuses"); - t::lib::Mocks::mock_preference('Reference_NFL_Statuses', '1|2'); + t::lib::Mocks::mock_preference( 'Reference_NFL_Statuses', '2' ); + $xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber, [] ); + like( $xml, qr{reallynotforloan}, "reallynotforloan when we change Reference_NFL_Statuses" ); + t::lib::Mocks::mock_preference( 'Reference_NFL_Statuses', q{} ); # empty, same effect + $xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber, [] ); + like( $xml, qr{reallynotforloan}, "reallynotforloan when we empty Reference_NFL_Statuses" ); + t::lib::Mocks::mock_preference( 'Reference_NFL_Statuses', '1|2' ); } $item->onloan('2001-01-01')->store; - $xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber,[]); - like( $xml, qr/other<\/status>/, "Checked out is part of other statuses" ); - like($xml,qr{Checked out},"Checked out status takes precedence over Not for loan"); + $xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber, [] ); + like( $xml, qr/other<\/status>/, "Checked out is part of other statuses" ); + like( $xml, qr{Checked out}, "Checked out status takes precedence over Not for loan" ); $item->withdrawn(1)->store; - $xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber,[]); - like($xml,qr{Withdrawn},"Withdrawn status takes precedence over Checked out"); + $xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber, [] ); + like( $xml, qr{Withdrawn}, "Withdrawn status takes precedence over Checked out" ); $item->itemlost(1)->store; - $xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber,[]); - like($xml,qr{Lost},"Lost status takes precedence over Withdrawn"); + $xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber, [] ); + like( $xml, qr{Lost}, "Lost status takes precedence over Withdrawn" ); $item->damaged(1)->store; - $xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber,[]); - like($xml,qr{Damaged},"Damaged status takes precedence over Lost"); + $xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber, [] ); + like( $xml, qr{Damaged}, "Damaged status takes precedence over Lost" ); - $builder->build({ source => "Branchtransfer", value => { - itemnumber => $item->itemnumber, - datearrived => undef, - datecancelled => undef, + $builder->build( + { + source => "Branchtransfer", + value => { + itemnumber => $item->itemnumber, + datearrived => undef, + datecancelled => undef, + } } - }); - $xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber,[]); - like($xml,qr{In transit},"In-transit status takes precedence over Damaged"); - - my $hold = $builder->build_object({ class => 'Koha::Holds', value => { - biblionumber => $item->biblionumber, - itemnumber => $item->itemnumber, - found => 'W', - priority => 0, + ); + $xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber, [] ); + like( $xml, qr{In transit}, "In-transit status takes precedence over Damaged" ); + + my $hold = $builder->build_object( + { + class => 'Koha::Holds', + value => { + biblionumber => $item->biblionumber, + itemnumber => $item->itemnumber, + found => 'W', + priority => 0, + } } - }); - $xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber,[]); - like($xml,qr{Hold waiting},"Waiting status takes precedence over In transit (holds)"); + ); + $xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber, [] ); + like( $xml, qr{Hold waiting}, "Waiting status takes precedence over In transit (holds)" ); $hold->cancel; - $builder->build({ source => "TmpHoldsqueue", value => { - itemnumber => $item->itemnumber - } - }); - $xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber,[]); - like($xml,qr{Pending hold},"Pending status takes precedence over all"); + $builder->build( { source => "TmpHoldsqueue", value => { itemnumber => $item->itemnumber } } ); + $xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber, [] ); + like( $xml, qr{Pending hold}, "Pending status takes precedence over all" ); my $library_name = $holdinglibrary->branchname; - like($xml,qr{${library_name}}, "Found resultbranch / holding branch" ); + like( $xml, qr{${library_name}}, "Found resultbranch / holding branch" ); - t::lib::Mocks::mock_preference('UseRecalls', 1); + t::lib::Mocks::mock_preference( 'UseRecalls', 1 ); my $recall = $builder->build_object( { class => 'Koha::Recalls', @@ -227,20 +252,23 @@ subtest 'buildKohaItemsNamespace status tests' => sub { } ); $recall->set_waiting; - $xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber,[]); - like($xml,qr{Recall waiting},"Waiting status takes precedence over In transit (recalls)"); - t::lib::Mocks::mock_preference('UseRecalls', 0); + $xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber, [] ); + like( + $xml, qr{Recall waiting}, + "Waiting status takes precedence over In transit (recalls)" + ); + t::lib::Mocks::mock_preference( 'UseRecalls', 0 ); $schema->storage->txn_rollback; }; subtest 'CustomXSLTExportList: Check export options' => sub { plan tests => 2; - t::lib::Mocks::mock_preference('OpacExportOptions', 'custom'); + t::lib::Mocks::mock_preference( 'OpacExportOptions', 'custom' ); my $list = C4::XSLT::CustomXSLTExportList(1); - is( $list>0, 1, 'We expect at least one result: simple export' ); + is( $list > 0, 1, 'We expect at least one result: simple export' ); $cache->clear_from_cache('CustomXSLTExportListOPAC'); - t::lib::Mocks::mock_preference('OpacExportOptions', 'dc'); + t::lib::Mocks::mock_preference( 'OpacExportOptions', 'dc' ); $list = C4::XSLT::CustomXSLTExportList(1); is( @$list, 0, 'We expect an empty list now' ); }; @@ -250,19 +278,19 @@ subtest 'buildKohaItemsNamespace() including/omitting items tests' => sub { $schema->storage->txn_begin; - my $biblio = $builder->build_sample_biblio; + my $biblio = $builder->build_sample_biblio; my $biblio2 = $builder->build_sample_biblio; # Have two known libraries for testing purposes - my $library_1 = $builder->build_object({ class => 'Koha::Libraries' }); - my $library_2 = $builder->build_object({ class => 'Koha::Libraries' }); - my $library_3 = $builder->build_object({ class => 'Koha::Libraries' }); + my $library_1 = $builder->build_object( { class => 'Koha::Libraries' } ); + my $library_2 = $builder->build_object( { class => 'Koha::Libraries' } ); + my $library_3 = $builder->build_object( { class => 'Koha::Libraries' } ); - my $item_1 = $builder->build_sample_item({ biblionumber => $biblio->biblionumber, library => $library_1->id }); - my $item_2 = $builder->build_sample_item({ biblionumber => $biblio->biblionumber, library => $library_2->id }); - my $item_3 = $builder->build_sample_item({ biblionumber => $biblio->biblionumber, library => $library_3->id }); + my $item_1 = $builder->build_sample_item( { biblionumber => $biblio->biblionumber, library => $library_1->id } ); + my $item_2 = $builder->build_sample_item( { biblionumber => $biblio->biblionumber, library => $library_2->id } ); + my $item_3 = $builder->build_sample_item( { biblionumber => $biblio->biblionumber, library => $library_3->id } ); - my $items_rs = $biblio->items->search({ "me.itemnumber" => { '!=' => $item_3->itemnumber } }); + my $items_rs = $biblio->items->search( { "me.itemnumber" => { '!=' => $item_3->itemnumber } } ); ## Test passing items_rs only my $xml = C4::XSLT::buildKohaItemsNamespace( $biblio->biblionumber, undef, $items_rs ); @@ -271,26 +299,30 @@ subtest 'buildKohaItemsNamespace() including/omitting items tests' => sub { my $library_2_name = $library_2->branchname; my $library_3_name = $library_3->branchname; - like( $xml, qr{$library_1_name}, '$item_1 present in the XML' ); - like( $xml, qr{$library_2_name}, '$item_2 present in the XML' ); + like( $xml, qr{$library_1_name}, '$item_1 present in the XML' ); + like( $xml, qr{$library_2_name}, '$item_2 present in the XML' ); unlike( $xml, qr{$library_3_name}, '$item_3 not present in the XML' ); - t::lib::Mocks::mock_preference('OpacHiddenItems', 'biblionumber: ['.$biblio2->biblionumber.']'); - my $hid_rs = $biblio->items->search({ "me.itemnumber" => { '!=' => $item_3->itemnumber } })->filter_by_visible_in_opac(); + t::lib::Mocks::mock_preference( 'OpacHiddenItems', 'biblionumber: [' . $biblio2->biblionumber . ']' ); + my $hid_rs = + $biblio->items->search( { "me.itemnumber" => { '!=' => $item_3->itemnumber } } )->filter_by_visible_in_opac(); $xml = C4::XSLT::buildKohaItemsNamespace( $biblio->biblionumber, undef, $hid_rs ); - like( $xml, qr{$library_1_name}, '$item_1 present in the XML' ); - like( $xml, qr{$library_2_name}, '$item_2 present in the XML' ); + like( $xml, qr{$library_1_name}, '$item_1 present in the XML' ); + like( $xml, qr{$library_2_name}, '$item_2 present in the XML' ); unlike( $xml, qr{$library_3_name}, '$item_3 not present in the XML' ); ## Test passing one item in hidden_items and items_rs $xml = C4::XSLT::buildKohaItemsNamespace( $biblio->biblionumber, [ $item_1->itemnumber ], $items_rs->reset ); unlike( $xml, qr{$library_1_name}, '$item_1 not present in the XML' ); - like( $xml, qr{$library_2_name}, '$item_2 present in the XML' ); + like( $xml, qr{$library_2_name}, '$item_2 present in the XML' ); unlike( $xml, qr{$library_3_name}, '$item_3 not present in the XML' ); ## Test passing both items in hidden_items and items_rs - $xml = C4::XSLT::buildKohaItemsNamespace( $biblio->biblionumber, [ $item_1->itemnumber, $item_2->itemnumber ], $items_rs->reset ); + $xml = C4::XSLT::buildKohaItemsNamespace( + $biblio->biblionumber, [ $item_1->itemnumber, $item_2->itemnumber ], + $items_rs->reset + ); unlike( $xml, qr{$library_1_name}, '$item_1 not present in the XML' ); unlike( $xml, qr{$library_2_name}, '$item_2 not present in the XML' ); @@ -298,7 +330,10 @@ subtest 'buildKohaItemsNamespace() including/omitting items tests' => sub { is( $xml, '', 'Empty XML' ); ## Test passing both items in hidden_items and no items_rs - $xml = C4::XSLT::buildKohaItemsNamespace( $biblio->biblionumber, [ $item_1->itemnumber, $item_2->itemnumber, $item_3->itemnumber ] ); + $xml = C4::XSLT::buildKohaItemsNamespace( + $biblio->biblionumber, + [ $item_1->itemnumber, $item_2->itemnumber, $item_3->itemnumber ] + ); unlike( $xml, qr{$library_1_name}, '$item_1 not present in the XML' ); unlike( $xml, qr{$library_2_name}, '$item_2 not present in the XML' ); @@ -309,8 +344,8 @@ subtest 'buildKohaItemsNamespace() including/omitting items tests' => sub { $xml = C4::XSLT::buildKohaItemsNamespace( $biblio->biblionumber, [ $item_1->itemnumber ] ); unlike( $xml, qr{$library_1_name}, '$item_1 not present in the XML' ); - like( $xml, qr{$library_2_name}, '$item_2 present in the XML' ); - like( $xml, qr{$library_3_name}, '$item_3 present in the XML' ); + like( $xml, qr{$library_2_name}, '$item_2 present in the XML' ); + like( $xml, qr{$library_3_name}, '$item_3 present in the XML' ); ## Test not passing any param $xml = C4::XSLT::buildKohaItemsNamespace( $biblio->biblionumber ); --- a/virtualshelves/downloadshelf.pl +++ a/virtualshelves/downloadshelf.pl @@ -27,7 +27,6 @@ use C4::Record; use C4::Ris qw( marc2ris ); use C4::XSLT qw( XSLTParse4Display ); - use Koha::Biblios; use Koha::CsvProfiles; use Koha::Virtualshelves; @@ -35,12 +34,12 @@ use Koha::Virtualshelves; use utf8; my $query = CGI->new; -my ( $template, $loggedinuser, $cookie ) = get_template_and_user ( +my ( $template, $loggedinuser, $cookie ) = get_template_and_user( { - template_name => "virtualshelves/downloadshelf.tt", - query => $query, - type => "intranet", - flagsrequired => { catalogue => 1 }, + template_name => "virtualshelves/downloadshelf.tt", + query => $query, + type => "intranet", + flagsrequired => { catalogue => 1 }, } ); @@ -49,44 +48,41 @@ my $format = $query->param('format'); my $dbh = C4::Context->dbh; my @messages; -if ($shelfid && $format) { +if ( $shelfid && $format ) { - my $marcflavour = C4::Context->preference('marcflavour'); - my $output=''; + my $marcflavour = C4::Context->preference('marcflavour'); + my $output = ''; my $shelf = Koha::Virtualshelves->find($shelfid); - if ( $shelf ) { - if ( $shelf->can_be_viewed( $loggedinuser ) ) { + if ($shelf) { + if ( $shelf->can_be_viewed($loggedinuser) ) { my $contents = $shelf->get_contents; + # CSV - if ($format =~ /^\d+$/) { + if ( $format =~ /^\d+$/ ) { my @biblios; while ( my $content = $contents->next ) { push @biblios, $content->biblionumber; } - $output = marc2csv(\@biblios, $format); - } - else { #Other formats + $output = marc2csv( \@biblios, $format ); + } else { #Other formats while ( my $content = $contents->next ) { my $biblionumber = $content->biblionumber; - my $biblio = Koha::Biblios->find($biblionumber); - my $record = $biblio->metadata->record({ embed_items => 1 }); - my $xslFile = $query->param("file"); - if ($format eq 'iso2709') { + my $biblio = Koha::Biblios->find($biblionumber); + my $record = $biblio->metadata->record( { embed_items => 1 } ); + my $xslFile = $query->param("file"); + if ( $format eq 'iso2709' ) { $output .= $record->as_usmarc(); - } - elsif ($format eq 'ris') { + } elsif ( $format eq 'ris' ) { $output .= marc2ris($record); - } - elsif ($format eq 'bibtex') { - $output .= marc2bibtex($record, $biblionumber); - } - elsif ($format =~ /^xsl\.(.*)$/){ + } elsif ( $format eq 'bibtex' ) { + $output .= marc2bibtex( $record, $biblionumber ); + } elsif ( $format =~ /^xsl\.(.*)$/ ) { $output .= XSLTParse4Display( { biblionumber => $biblionumber, - record => $record, + record => $record, xsl_syspref => 'XSLTCustomExport', fix_amps => 1, hidden_items => undef, @@ -98,12 +94,13 @@ if ($shelfid && $format) { } # If it was a CSV export we change the format after the export so the file extension is fine - $format = "csv" if ($format =~ m/^\d+$/); - $format = "html" if ($format =~ /^xsl\./); + $format = "csv" if ( $format =~ m/^\d+$/ ); + $format = "html" if ( $format =~ /^xsl\./ ); print $query->header( - -type => 'application/octet-stream', - -'Content-Transfer-Encoding' => 'binary', - -attachment=>"shelf.$format"); + -type => 'application/octet-stream', + -'Content-Transfer-Encoding' => 'binary', + -attachment => "shelf.$format" + ); print $output; exit; } else { @@ -112,10 +109,10 @@ if ($shelfid && $format) { } else { push @messages, { type => 'error', code => 'does_not_exist' }; } -} -else { - $template->param(csv_profiles => [ Koha::CsvProfiles->search({ type => 'marc', used_for => 'export_records' })->as_list ]); - $template->param(shelfid => $shelfid); +} else { + $template->param( + csv_profiles => [ Koha::CsvProfiles->search( { type => 'marc', used_for => 'export_records' } )->as_list ] ); + $template->param( shelfid => $shelfid ); } $template->param( messages => \@messages ); output_html_with_http_headers $query, $cookie, $template->output; --- a/virtualshelves/shelves.pl +++ a/virtualshelves/shelves.pl @@ -385,15 +385,15 @@ if ( $op eq 'view' ) { } $template->param( - op => $op, - referer => $referer, - shelf => $shelf, - messages => \@messages, - public => $public, - print => scalar $query->param('print') || 0, - csv_profiles => [ Koha::CsvProfiles->search({ type => 'marc', used_for => 'export_records' })->as_list ], + op => $op, + referer => $referer, + shelf => $shelf, + messages => \@messages, + public => $public, + print => scalar $query->param('print') || 0, + csv_profiles => [ Koha::CsvProfiles->search({ type => 'marc', used_for => 'export_records' })->as_list ], allow_transfer => $allow_transfer, - xsl_exports => CustomXSLTExportList() + xsl_exports => CustomXSLTExportList() ); output_html_with_http_headers $query, $cookie, $template->output; --