From a12c0d421d6f038886c1db86723a285aa084ae2b Mon Sep 17 00:00:00 2001 From: Jonathan Druart Date: Wed, 26 Nov 2014 13:50:50 +0100 Subject: [PATCH] Bug 13345: Allow patrons to choose format on sending basket/list by email It is already possible to download a basket(cart) or a list using different format. But by email, only iso2709 is possible. This patch adds the ability to select a format for the file attached to the email when sending the basket/list content. Test plan: 1/ At the OPAC, add some records to your basket and send it by email using different formats (RIS, BibTeX, MARC and the CSV profiles defined). 2/ At the OPAC, add some records to a list and send it by email using the different formats. 3/ Redo step 1 at the intranet 4/ Redo step 2 at the intranet Not that subtitles are not displayed in all these cases. Note for QA: This patch refactors 3 main things: 1/ Template side: the dropdown list to select the format is now in an include file (indeed, this list is used in 4 templates, this will make easier further changes). The include files are named 'download-export-available-formats.inc', feel free to suggest something better. The are used in: [opac-]sendbasket.tt, [opac-]sendshelf.tt, [opac-]downloadbasket.tt and [opac-]downloadshelf.tt. 2/ Build records data and the records file This job was done in 4 scripts: - opac/opac-sendbasket.pl - opac/opac-sendshelf.pl - basket/sendbasket.pl - virtualshelves/sendshelf.pl Now it's done in C4::Biblio::BuildBiblioDataForExport and tests are provided in t/db_dependent/Biblio/BuildBiblioDataForExport.t Not that a similar job is done in [opac-]downloadcart.pl and [opac-]downloadshelf.pl 3/ Build the subject and body of the email sent Same as before, the job was done at the same places. Now it's done in Koha::Email->fill_body_for_sending (feel free to suggestion a better name) and tests are provided in t/Koha_Email.t Some tests for BuildBiblioDataForExport can fail if bug 13360 is not pushed yet. Sponsored-by: Mines Paristech Signed-off-by: Nicole C. Engard --- C4/Biblio.pm | 66 ++++++++++ Koha/Email.pm | 75 +++++++++++ basket/basket.pl | 6 +- basket/downloadcart.pl | 1 - basket/sendbasket.pl | 114 ++++------------- .../includes/download-export-available-formats.inc | 9 ++ .../prog/en/modules/basket/downloadcart.tt | 17 +-- .../prog/en/modules/basket/sendbasket.tt | 6 +- .../prog/en/modules/basket/sendbasketform.tt | 34 ++--- .../en/modules/virtualshelves/downloadshelf.tt | 18 +-- .../en/modules/virtualshelves/sendshelfform.tt | 34 ++--- .../includes/download-export-available-formats.inc | 10 ++ .../bootstrap/en/modules/opac-downloadcart.tt | 11 +- .../bootstrap/en/modules/opac-downloadshelf.tt | 11 +- .../bootstrap/en/modules/opac-sendbasket.tt | 6 +- .../bootstrap/en/modules/opac-sendbasketform.tt | 2 + .../bootstrap/en/modules/opac-sendshelfform.tt | 5 +- opac/opac-downloadcart.pl | 9 +- opac/opac-downloadshelf.pl | 7 +- opac/opac-sendbasket.pl | 123 +++++------------- opac/opac-sendshelf.pl | 117 +++++------------ t/Koha_Email.t | 77 +++++++++++- t/data/templates/send_by_email.tt | 11 ++ t/db_dependent/Biblio/BuildBiblioDataForExport.t | 139 +++++++++++++++++++++ virtualshelves/downloadshelf.pl | 1 - virtualshelves/sendshelf.pl | 115 +++++------------ 26 files changed, 575 insertions(+), 449 deletions(-) create mode 100644 koha-tmpl/intranet-tmpl/prog/en/includes/download-export-available-formats.inc create mode 100644 koha-tmpl/opac-tmpl/bootstrap/en/includes/download-export-available-formats.inc create mode 100644 t/data/templates/send_by_email.tt create mode 100644 t/db_dependent/Biblio/BuildBiblioDataForExport.t diff --git a/C4/Biblio.pm b/C4/Biblio.pm index 10faa83..ba6149d 100644 --- a/C4/Biblio.pm +++ b/C4/Biblio.pm @@ -37,6 +37,7 @@ use C4::ClassSource; use C4::Charset; use C4::Linker; use C4::OAI::Sets; +use C4::Ris; use Koha::Cache; use Koha::Authority::Types; @@ -3808,6 +3809,71 @@ sub RemoveAllNsb { return $record; } +sub BuildBiblioDataForExport { + my ( $params ) = @_; + my $biblionumbers = $params->{biblionumbers}; + my $format = $params->{format}; + my $template = $params->{template}; # Only used for ISBD + my ( @records_data, $records_file ); + + # CSV + if ($format eq 'csv' ) { + + # FIXME should be used at the beginning of this module + # But compilation explodes... + require C4::Record; + $records_file = C4::Record::marc2csv($biblionumbers, $params->{csv_profile_id}); + + # Other formats + } else { + # retrieve biblios from shelf + my $marcflavour = C4::Context->preference('marcflavour'); + foreach my $biblionumber (@$biblionumbers) { + my $dat = GetBiblioData($biblionumber); + next unless $dat; + my $record = GetMarcBiblio($biblionumber, 1); + my $marcnotesarray = GetMarcNotes( $record, $marcflavour ); + my $marcauthorsarray = GetMarcAuthors( $record, $marcflavour ); + my $marcsubjctsarray = GetMarcSubjects( $record, $marcflavour ); + my $fw = GetFrameworkCode($biblionumber); + my $subtitle = GetRecordValue( 'subtitle', $record, $fw ); + + my @items = C4::Items::GetItemsInfo( $biblionumber ); + + my $hasauthors = 0; + if($dat->{'author'} || @$marcauthorsarray) { + $hasauthors = 1; + } + + $dat->{MARCNOTES} = $marcnotesarray; + $dat->{MARCSUBJCTS} = $marcsubjctsarray; + $dat->{MARCAUTHORS} = $marcauthorsarray; + $dat->{HASAUTHORS} = $hasauthors; + $dat->{biblionumber} = $biblionumber; + $dat->{ITEM_RESULTS} = \@items; + $dat->{subtitle} = $subtitle; + + if ($format eq 'iso2709') { + $records_file .= $record->as_usmarc(); + } + elsif ($format eq 'ris') { + $records_file .= C4::Ris::marc2ris($record); + } + elsif ($format eq 'bibtex') { + $records_file .= C4::Record::marc2bibtex($record, $biblionumber); + } + elsif ( $format eq 'isbd' ) { + # Only called from the OPAC at the moment + $records_file .= C4::Biblio::GetISBDView($biblionumber, $template); + } + + push( @records_data, $dat ); + } + } + + return { records_file => $records_file, records_data => \@records_data }; +} + 1; diff --git a/Koha/Email.pm b/Koha/Email.pm index fc392a3..c11e670 100644 --- a/Koha/Email.pm +++ b/Koha/Email.pm @@ -18,6 +18,9 @@ package Koha::Email; use Modern::Perl; +use Encode qw( encode ); +use MIME::QuotedPrint; +use MIME::Base64; use base qw(Class::Accessor); use C4::Context; @@ -60,6 +63,78 @@ sub create_message_headers { $mail{'Message'} = $params->{message} if $params->{message}; $mail{'Subject'} = $params->{subject} if $params->{subject}; $mail{'Content-Type'} = $params->{contenttype} if $params->{contenttype}; + $self->{mail} = \%mail; return %mail; } + +sub fill_body_for_sending { + my ( $self, $params ) = @_; + my $template = $params->{template}; + my $default_filename = $params->{default_filename}; + my $attachment = $params->{attachment}; + + my %mail = %{ $self->{mail} }; + + # Analysing information and getting mail properties + if ( $template =~ /(.*)/s ) { + $mail{Subject} = $1; + $mail{Subject} =~ s|\n?(.*)\n?|$1|; + $mail{Subject} = Encode::encode("UTF-8", $mail{Subject}); + } + else { $mail{Subject} = "no subject"; } + + my $email_header = ""; + if ( $template =~ /
(.*)/s ) { + $email_header = $1; + $email_header =~ s|\n?(.*)\n?|$1|; + $email_header = encode_qp(Encode::encode("UTF-8", $email_header)); + } + + if ( $template =~ /(.*)/s ) { + $default_filename = $1; + $default_filename =~ s|\n?(.*)\n?|$1|; + } + + my $body; + if ( $template =~ /(.*)/s ) { + $body = $1; + $body =~ s|\n?(.*)\n?|$1|; + $body = encode_qp(Encode::encode("UTF-8", $body)); + } + + my $boundary = "====" . time() . "===="; + + # We set and put the multipart content + $mail{'Content-Type'} = qq|multipart/mixed; boundary="$boundary"|; + + # If the attachement is a csv file, it's already encoded + # See C4::Record::marc2csv which calls C4::Record::marcrecord2csv + unless ( $default_filename =~ m|.csv$| ) { + $attachment = Encode::encode( "UTF-8", $attachment ) + } + my $file = encode_base64( $attachment ); + $boundary = '--' . $boundary; + + $mail{body} = <{mail} = \%mail; + + return %mail; +} + 1; diff --git a/basket/basket.pl b/basket/basket.pl index 1dfbdb8..07db0e5 100755 --- a/basket/basket.pl +++ b/basket/basket.pl @@ -15,16 +15,14 @@ # You should have received a copy of the GNU General Public License # along with Koha; if not, see . - -use strict; -use warnings; +use Modern::Perl; use CGI qw ( -utf8 ); use C4::Koha; use C4::Biblio; use C4::Items; use C4::Auth; use C4::Output; -use C4::Csv; +use C4::Csv qw( GetCsvProfilesLoop ); my $query = new CGI; diff --git a/basket/downloadcart.pl b/basket/downloadcart.pl index 17e5617..af71280 100755 --- a/basket/downloadcart.pl +++ b/basket/downloadcart.pl @@ -21,7 +21,6 @@ use strict; use warnings; use CGI qw ( -utf8 ); -use Encode qw(encode); use C4::Auth; use C4::Biblio; diff --git a/basket/sendbasket.pl b/basket/sendbasket.pl index 83dab55..1948c74 100755 --- a/basket/sendbasket.pl +++ b/basket/sendbasket.pl @@ -15,21 +15,18 @@ # You should have received a copy of the GNU General Public License # along with Koha; if not, see . -use strict; -use warnings; +use Modern::Perl; use CGI qw ( -utf8 ); -use Encode qw(encode); use Carp; use Mail::Sendmail; -use MIME::QuotedPrint; -use MIME::Base64; use C4::Biblio; use C4::Items; use C4::Auth; use C4::Output; use C4::Biblio; +use C4::Csv qw( GetCsvProfilesLoop ); use Koha::Email; my $query = new CGI; @@ -46,6 +43,7 @@ my ( $template, $borrowernumber, $cookie ) = get_template_and_user ( my $bib_list = $query->param('bib_list'); my $email_add = $query->param('email_add'); +my $format = $query->param('format') || 'iso2709'; my $dbh = C4::Context->dbh; @@ -63,98 +61,37 @@ if ( $email_add ) { } ); - my @bibs = split( /\//, $bib_list ); - my @results; - my $iso2709; - my $marcflavour = C4::Context->preference('marcflavour'); - foreach my $biblionumber (@bibs) { - $template2->param( biblionumber => $biblionumber ); - - my $dat = GetBiblioData($biblionumber); - next unless $dat; - my $record = GetMarcBiblio($biblionumber, 1); - my $marcnotesarray = GetMarcNotes( $record, $marcflavour ); - my $marcauthorsarray = GetMarcAuthors( $record, $marcflavour ); - my $marcsubjctsarray = GetMarcSubjects( $record, $marcflavour ); - - my @items = GetItemsInfo( $biblionumber ); - - my $hasauthors = 0; - if($dat->{'author'} || @$marcauthorsarray) { - $hasauthors = 1; - } - - - $dat->{MARCNOTES} = $marcnotesarray; - $dat->{MARCSUBJCTS} = $marcsubjctsarray; - $dat->{MARCAUTHORS} = $marcauthorsarray; - $dat->{HASAUTHORS} = $hasauthors; - $dat->{'biblionumber'} = $biblionumber; - $dat->{ITEM_RESULTS} = \@items; - - $iso2709 .= $record->as_usmarc(); - - push( @results, $dat ); + my $csv_profile_id; + if ( $format =~ m|^\d+$| ) { + $csv_profile_id = $format; + $format = 'csv'; } + my @biblionumbers = split( /\//, $bib_list ); + my $data = C4::Biblio::BuildBiblioDataForExport( + { + biblionumbers => \@biblionumbers, + format => $format, + csv_profile_id => $csv_profile_id + } + ); + my $records_file = $data->{records_file}; + my $records_data = $data->{records_data}; - my $resultsarray = \@results; $template2->param( - BIBLIO_RESULTS => $resultsarray, + BIBLIO_RESULTS => $records_data, comment => $comment ); # Getting template result my $template_res = $template2->output(); - my $body; - - # Analysing information and getting mail properties - if ( $template_res =~ /(.*)/s ) { - $mail{subject} = $1; - $mail{subject} =~ s|\n?(.*)\n?|$1|; - $mail{subject} = Encode::encode("UTF-8", $mail{subject}); - } - else { $mail{'subject'} = "no subject"; } - my $email_header = ""; - if ( $template_res =~ /
(.*)/s ) { - $email_header = $1; - $email_header =~ s|\n?(.*)\n?|$1|; - $email_header = encode_qp(Encode::encode("UTF-8", $email_header)); - } - - my $email_file = "basket.txt"; - if ( $template_res =~ /(.*)/s ) { - $email_file = $1; - $email_file =~ s|\n?(.*)\n?|$1|; - } - - if ( $template_res =~ /(.*)/s ) { - $body = $1; - $body =~ s|\n?(.*)\n?|$1|; - $body = encode_qp(Encode::encode("UTF-8", $body)); - } - - my $boundary = "====" . time() . "===="; - - # Writing mail - $mail{'content-type'} = "multipart/mixed; boundary=\"$boundary\""; - my $isofile = encode_base64(encode("UTF-8", $iso2709)); - $boundary = '--' . $boundary; - $mail{body} = <fill_body_for_sending( + { + template => $template_res, + default_filename => "basket.$format", + attachment => $records_file, + } + ); # Sending mail if ( sendmail %mail ) { @@ -175,6 +112,7 @@ else { url => "/cgi-bin/koha/basket/sendbasket.pl", suggestion => C4::Context->preference("suggestion"), virtualshelves => C4::Context->preference("virtualshelves"), + csv_profiles => GetCsvProfilesLoop('marc'), ); output_html_with_http_headers $query, $cookie, $template->output; } diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/download-export-available-formats.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/download-export-available-formats.inc new file mode 100644 index 0000000..4aec38a --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/download-export-available-formats.inc @@ -0,0 +1,9 @@ + diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/basket/downloadcart.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/basket/downloadcart.tt index a343bd8..f81839a 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/basket/downloadcart.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/basket/downloadcart.tt @@ -9,18 +9,11 @@
Download cart -
  1. - -
  2. +
      +
    1. + + [% INCLUDE 'download-export-available-formats.inc' %] +
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/basket/sendbasket.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/basket/sendbasket.tt index c99b54e..3e97dd6 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/basket/sendbasket.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/basket/sendbasket.tt @@ -30,7 +30,11 @@ Your cart
  • [% BIBLIO_RESULT.title %] - [% IF ( BIBLIO_RESULT.subtitle ) %] [% BIBLIO_RESULT.subtitle %][% END %] + [% IF ( BIBLIO_RESULT.subtitle.size ) %] + [% FOREACH subtitle IN BIBLIO_RESULT.subtitle %] + [% subtitle.subfield %] + [% END %] + [% END %]

    diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/basket/sendbasketform.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/basket/sendbasketform.tt index 93a0f9d..aeafb9a 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/basket/sendbasketform.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/basket/sendbasketform.tt @@ -17,21 +17,27 @@ [% ELSE %] - -

    -Sending your cart -
    1. - - -
    2. -
    3. - - -
    4. -
    5. +
      + Sending your cart +
        +
      1. + + +
      2. +
      3. + + +
      4. +
      5. + + [% INCLUDE 'download-export-available-formats.inc' %] +
      6. +
      +
      +
      -
    -
    Cancel
    + Cancel +
  • [% END %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/virtualshelves/downloadshelf.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/virtualshelves/downloadshelf.tt index 96fa994..7187ba0 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/virtualshelves/downloadshelf.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/virtualshelves/downloadshelf.tt @@ -26,18 +26,12 @@
    Download list -
    1. - - -
    +
      +
    1. + + [% INCLUDE 'download-export-available-formats.inc' %] +
    2. +
    Cancel diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/virtualshelves/sendshelfform.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/virtualshelves/sendshelfform.tt index 8c44afa..8124f55 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/virtualshelves/sendshelfform.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/virtualshelves/sendshelfform.tt @@ -16,21 +16,27 @@ [% ELSE %] - -
    -Sending your list -
    1. - - -
    2. -
    3. - - -
    4. -
    5. +
      + Sending your list +
        +
      1. + + +
      2. +
      3. + + +
      4. +
      5. + + [% INCLUDE 'download-export-available-formats.inc' %] +
      6. +
      +
      +
      -
    -
    Cancel
    + Cancel +
    [% END %] diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/includes/download-export-available-formats.inc b/koha-tmpl/opac-tmpl/bootstrap/en/includes/download-export-available-formats.inc new file mode 100644 index 0000000..cbef78a --- /dev/null +++ b/koha-tmpl/opac-tmpl/bootstrap/en/includes/download-export-available-formats.inc @@ -0,0 +1,10 @@ + diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-downloadcart.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-downloadcart.tt index f7eebd8..d0eef06 100644 --- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-downloadcart.tt +++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-downloadcart.tt @@ -11,16 +11,7 @@

    Download cart

    - + [% INCLUDE 'download-export-available-formats.inc' %]
    diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-downloadshelf.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-downloadshelf.tt index 4e4f832..6c1c62a 100644 --- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-downloadshelf.tt +++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-downloadshelf.tt @@ -50,16 +50,7 @@

    Download list [% shelf.shelfname %]

    - + [% INCLUDE 'download-export-available-formats.inc' %] Required
    diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-sendbasket.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-sendbasket.tt index e3c88ab..9ce0385 100644 --- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-sendbasket.tt +++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-sendbasket.tt @@ -30,7 +30,11 @@ Your cart
  • [% BIBLIO_RESULT.title %] - [% IF ( BIBLIO_RESULT.subtitle ) %] [% BIBLIO_RESULT.subtitle %][% END %] + [% IF ( BIBLIO_RESULT.subtitle.size ) %] + [% FOREACH subtitle IN BIBLIO_RESULT.subtitle %] + [% subtitle.subfield %] + [% END %] + [% END %]

    diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-sendbasketform.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-sendbasketform.tt index aa46c6a..5865fa8 100644 --- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-sendbasketform.tt +++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-sendbasketform.tt @@ -34,6 +34,8 @@ + + [% INCLUDE 'download-export-available-formats.inc' %]

  • diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-sendshelfform.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-sendshelfform.tt index 06a9c06..07e6cd8 100644 --- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-sendshelfform.tt +++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-sendshelfform.tt @@ -38,7 +38,10 @@ - + + [% INCLUDE 'download-export-available-formats.inc' %] + +
    diff --git a/opac/opac-downloadcart.pl b/opac/opac-downloadcart.pl index c5574e3..79adfe9 100755 --- a/opac/opac-downloadcart.pl +++ b/opac/opac-downloadcart.pl @@ -21,7 +21,6 @@ use strict; use warnings; use CGI qw ( -utf8 ); -use Encode qw(encode); use C4::Auth; use C4::Biblio; @@ -55,12 +54,13 @@ if ($bib_list && $format) { my $extension; my $type; - # CSV + # CSV if ($format =~ /^\d+$/) { $output = marc2csv(\@bibs, $format); + $format = 'csv'; - # Other formats + # Other formats } else { foreach my $biblio (@bibs) { @@ -84,9 +84,6 @@ if ($bib_list && $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+$/); - print $query->header( -type => ($type) ? $type : 'application/octet-stream', -'Content-Transfer-Encoding' => 'binary', diff --git a/opac/opac-downloadshelf.pl b/opac/opac-downloadshelf.pl index 94bdae1..7474318 100755 --- a/opac/opac-downloadshelf.pl +++ b/opac/opac-downloadshelf.pl @@ -21,7 +21,6 @@ use strict; use warnings; use CGI qw ( -utf8 ); -use Encode qw(encode); use C4::Auth; use C4::Biblio; @@ -69,6 +68,9 @@ if ( $shelf and $shelf->can_be_viewed( $borrowernumber ) ) { push @biblios, $content->biblionumber->biblionumber; } $output = marc2csv(\@biblios, $format); + + $format = 'csv'; + # Other formats } else { while ( my $content = $contents->next ) { @@ -94,9 +96,6 @@ 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+$/); - print $query->header( -type => ($type) ? $type : 'application/octet-stream', -'Content-Transfer-Encoding' => 'binary', diff --git a/opac/opac-sendbasket.pl b/opac/opac-sendbasket.pl index 6b2d62f..ab34197 100755 --- a/opac/opac-sendbasket.pl +++ b/opac/opac-sendbasket.pl @@ -17,22 +17,19 @@ # You should have received a copy of the GNU General Public License # along with Koha; if not, see . -use strict; -use warnings; +use Modern::Perl; use CGI qw ( -utf8 ); -use Encode qw(encode); use Carp; use Mail::Sendmail; -use MIME::QuotedPrint; -use MIME::Base64; use C4::Biblio; use C4::Items; use C4::Auth; use C4::Output; use C4::Biblio; use C4::Members; +use C4::Csv qw( GetCsvProfilesLoop ); use Koha::Email; my $query = new CGI; @@ -48,6 +45,7 @@ my ( $template, $borrowernumber, $cookie ) = get_template_and_user ( my $bib_list = $query->param('bib_list'); my $email_add = $query->param('email_add'); +my $format = $query->param('format') || 'iso2709'; my $dbh = C4::Context->dbh; @@ -76,44 +74,25 @@ if ( $email_add ) { } ); - my @bibs = split( /\//, $bib_list ); - my @results; - my $iso2709; - my $marcflavour = C4::Context->preference('marcflavour'); - foreach my $biblionumber (@bibs) { - $template2->param( biblionumber => $biblionumber ); - - my $dat = GetBiblioData($biblionumber); - next unless $dat; - my $record = GetMarcBiblio($biblionumber, 1); - my $marcnotesarray = GetMarcNotes( $record, $marcflavour ); - my $marcauthorsarray = GetMarcAuthors( $record, $marcflavour ); - my $marcsubjctsarray = GetMarcSubjects( $record, $marcflavour ); - - my @items = GetItemsInfo( $biblionumber ); - - my $hasauthors = 0; - if($dat->{'author'} || @$marcauthorsarray) { - $hasauthors = 1; - } - - - $dat->{MARCNOTES} = $marcnotesarray; - $dat->{MARCSUBJCTS} = $marcsubjctsarray; - $dat->{MARCAUTHORS} = $marcauthorsarray; - $dat->{HASAUTHORS} = $hasauthors; - $dat->{'biblionumber'} = $biblionumber; - $dat->{ITEM_RESULTS} = \@items; - - $iso2709 .= $record->as_usmarc(); - - push( @results, $dat ); + my $csv_profile_id; + if ( $format =~ m|^\d+$| ) { + $csv_profile_id = $format; + $format = 'csv'; } + my @biblionumbers = split( /\//, $bib_list ); + my $data = C4::Biblio::BuildBiblioDataForExport( + { + biblionumbers => \@biblionumbers, + format => $format, + csv_profile_id => $csv_profile_id, + template => 'opac', + } + ); + my $records_file = $data->{records_file}; + my $records_data = $data->{records_data}; - my $resultsarray = \@results; - $template2->param( - BIBLIO_RESULTS => $resultsarray, + BIBLIO_RESULTS => $records_data, comment => $comment, firstname => $user->{firstname}, surname => $user->{surname}, @@ -121,68 +100,23 @@ if ( $email_add ) { # Getting template result my $template_res = $template2->output(); - my $body; - - # Analysing information and getting mail properties - - if ( $template_res =~ /(.*)/s ) { - $mail{subject} = $1; - $mail{subject} =~ s|\n?(.*)\n?|$1|; - $mail{subject} = Encode::encode("UTF-8", $mail{subject}); - } - else { $mail{'subject'} = "no subject"; } - - my $email_header = ""; - if ( $template_res =~ /
    (.*)/s ) { - $email_header = $1; - $email_header =~ s|\n?(.*)\n?|$1|; - $email_header = encode_qp(Encode::encode("UTF-8", $email_header)); - } - my $email_file = "basket.txt"; - if ( $template_res =~ /(.*)/s ) { - $email_file = $1; - $email_file =~ s|\n?(.*)\n?|$1|; - } - - if ( $template_res =~ /(.*)/s ) { - $body = $1; - $body =~ s|\n?(.*)\n?|$1|; - $body = encode_qp(Encode::encode("UTF-8", $body)); - } - - $mail{body} = $body; - - my $boundary = "====" . time() . "===="; - - $mail{'content-type'} = "multipart/mixed; boundary=\"$boundary\""; - my $isofile = encode_base64(encode("UTF-8", $iso2709)); - $boundary = '--' . $boundary; - $mail{body} = <fill_body_for_sending( + { + template => $template_res, + default_filename => "basket.$format", + attachment => $records_file, + } + ); # Sending mail (if not empty basket) - if ( defined($iso2709) && sendmail %mail ) { + if ( defined($records_file) && sendmail %mail ) { # do something if it works.... $template->param( SENT => "1" ); } else { # do something if it doesnt work.... - carp "Error sending mail: empty basket" if !defined($iso2709); + carp "Error sending mail: empty basket" unless defined($records_file); carp "Error sending mail: $Mail::Sendmail::error" if $Mail::Sendmail::error; $template->param( error => 1 ); } @@ -195,6 +129,7 @@ else { url => "/cgi-bin/koha/opac-sendbasket.pl", suggestion => C4::Context->preference("suggestion"), virtualshelves => C4::Context->preference("virtualshelves"), + csv_profiles => GetCsvProfilesLoop('marc'), ); output_html_with_http_headers $query, $cookie, $template->output; } diff --git a/opac/opac-sendshelf.pl b/opac/opac-sendshelf.pl index 8d39c93..1eafc3d 100755 --- a/opac/opac-sendshelf.pl +++ b/opac/opac-sendshelf.pl @@ -17,21 +17,18 @@ # You should have received a copy of the GNU General Public License # along with Koha; if not, see . -use strict; -use warnings; +use Modern::Perl; use CGI qw ( -utf8 ); -use Encode qw( encode ); use Carp; use Mail::Sendmail; -use MIME::QuotedPrint; -use MIME::Base64; use C4::Auth; use C4::Biblio; use C4::Items; use C4::Output; use C4::Members; +use C4::Csv qw( GetCsvProfilesLoop ); use Koha::Email; use Koha::Virtualshelves; @@ -48,6 +45,7 @@ my ( $template, $borrowernumber, $cookie ) = get_template_and_user ( my $shelfid = $query->param('shelfid'); my $email = $query->param('email'); +my $format = $query->param('format') || 'iso2709'; my $dbh = C4::Context->dbh; @@ -73,42 +71,30 @@ if ( $email ) { } ); - my $shelf = Koha::Virtualshelves->find( $shelfid ); - my $contents = $shelf->get_contents; - my $marcflavour = C4::Context->preference('marcflavour'); - my $iso2709; - my @results; - - while ( my $content = $contents->next ) { - my $biblionumber = $content->biblionumber->biblionumber; - my $fw = GetFrameworkCode($biblionumber); - my $dat = GetBiblioData($biblionumber); - my $record = GetMarcBiblio($biblionumber, 1); - my $marcnotesarray = GetMarcNotes( $record, $marcflavour ); - my $marcauthorsarray = GetMarcAuthors( $record, $marcflavour ); - my $marcsubjctsarray = GetMarcSubjects( $record, $marcflavour ); - my $subtitle = GetRecordValue('subtitle', $record, $fw); - - my @items = GetItemsInfo( $biblionumber ); - - $dat->{ISBN} = GetMarcISBN($record, $marcflavour); - $dat->{MARCNOTES} = $marcnotesarray; - $dat->{MARCSUBJCTS} = $marcsubjctsarray; - $dat->{MARCAUTHORS} = $marcauthorsarray; - $dat->{'biblionumber'} = $biblionumber; - $dat->{ITEM_RESULTS} = \@items; - $dat->{subtitle} = $subtitle; - $dat->{HASAUTHORS} = $dat->{'author'} || @$marcauthorsarray; - - $iso2709 .= $record->as_usmarc(); - - push( @results, $dat ); + my @shelf = GetShelf($shelfid); + my ($items, $totitems) = GetShelfContents($shelfid); + + my $csv_profile_id; + if ( $format =~ m|^\d+$| ) { + $csv_profile_id = $format; + $format = 'csv'; } + my @biblionumbers = map { $_->{biblionumber} } @$items; + my $data = C4::Biblio::BuildBiblioDataForExport( + { + biblionumbers => \@biblionumbers, + format => $format, + csv_profile_id => $csv_profile_id, + template => 'opac', + } + ); + my $records_file = $data->{records_file}; + my $records_data = $data->{records_data}; my $user = GetMember(borrowernumber => $borrowernumber); $template2->param( - BIBLIO_RESULTS => \@results, + BIBLIO_RESULTS => $records_data, comment => $comment, shelfname => $shelf->shelfname, firstname => $user->{firstname}, @@ -119,57 +105,13 @@ if ( $email ) { my $template_res = $template2->output(); my $body; - # Analysing information and getting mail properties - if ( $template_res =~ /(.*)/s ) { - $mail{subject} = $1; - $mail{subject} =~ s|\n?(.*)\n?|$1|; - } - else { $mail{'subject'} = "no subject"; } - $mail{subject} = Encode::encode("UTF-8", $mail{subject}); - - my $email_header = ""; - if ( $template_res =~ /
    (.*)/s ) { - $email_header = $1; - $email_header =~ s|\n?(.*)\n?|$1|; - $email_header = encode_qp(Encode::encode("UTF-8", $email_header)); - } - - my $email_file = "list.txt"; - if ( $template_res =~ /(.*)/s ) { - $email_file = $1; - $email_file =~ s|\n?(.*)\n?|$1|; - } - - if ( $template_res =~ /(.*)/s ) { - $body = $1; - $body =~ s|\n?(.*)\n?|$1|; - $body = encode_qp(Encode::encode("UTF-8", $body)); - } - - my $boundary = "====" . time() . "===="; - - # We set and put the multipart content - $mail{'content-type'} = "multipart/mixed; boundary=\"$boundary\""; - - my $isofile = encode_base64(encode("UTF-8", $iso2709)); - $boundary = '--' . $boundary; - - $mail{body} = <fill_body_for_sending( + { + template => $template_res, + default_filename => "list.$format", + attachment => $records_file, + } + ); # Sending mail if ( sendmail %mail ) { @@ -192,6 +134,7 @@ END_OF_BODY }else{ $template->param( shelfid => $shelfid, url => "/cgi-bin/koha/opac-sendshelf.pl", + csv_profiles => GetCsvProfilesLoop('marc'), ); output_html_with_http_headers $query, $cookie, $template->output; } diff --git a/t/Koha_Email.t b/t/Koha_Email.t index 93dd55b..0c30b12 100755 --- a/t/Koha_Email.t +++ b/t/Koha_Email.t @@ -1,7 +1,13 @@ use Modern::Perl; +use MIME::QuotedPrint; +use MIME::Base64; +use Template; + use t::lib::Mocks; -use Test::More tests => 4; # last test to print +use Test::More tests => 6; + +use FindBin qw( $Bin ); use_ok('Koha::Email'); @@ -9,8 +15,73 @@ my $from = 'chrisc@catalyst.net.nz'; t::lib::Mocks::mock_preference('ReplytoDefault', $from); t::lib::Mocks::mock_preference('ReturnpathDefault', $from); - - ok( my $email = Koha::Email->new(), 'Create a Koha::Email Object'); ok( my %mail = $email->create_message_headers({from => $from}),'Set headers'); is ($mail{'From'}, $from, 'Set correctly'); + + +my $subject = q|My subject μΣ会é|; +my $header = q|My header μΣ会é|; +my $message = q|My Message μΣ会é|; + +my $template_filepath = $Bin . '/data/templates/send_by_email.tt'; +my $tt = Template->new( ENCODING => 'UTF-8', ABSOLUTE => 1 ); + +subtest 'csv' => sub { + plan tests => 5; + my $csv_attachment = q|title + "La Recherche" + "Problèmes politiques et sociaux" + "Sud Provence Côte d'Azur" + "The art of computer programming μΣ会é" + |; + # the csv is generated by C4::Record::marc2csv and is already encoded + $csv_attachment = Encode::encode('UTF-8', $csv_attachment); + + my $output; + $tt->process( $template_filepath, { test => 'pouet' }, \$output ); + + %mail = $email->fill_body_for_sending( + { + template => $output, + default_filename => 'myfile.csv', + attachment => $csv_attachment, + } + ); + + is ($mail{From}, $from, 'From is still set correctly'); + like( $mail{Subject}, qr{$subject}, ); + + my $encoded_header = encode_qp($header); + my $encoded_message = encode_qp($header); + my $encoded_csv_attachment = encode_base64($csv_attachment); + like( $mail{body}, qr{$encoded_header}, ); + like( $mail{body}, qr{$encoded_message}, ); + like( $mail{body}, qr{$encoded_csv_attachment}, ); +}; + +subtest 'iso2709' => sub { + plan tests => 5; + my $ris_attachment = qq|TY - BOOK\r\nAU - Knuth, Donald Ervin\r\nTI - The art of computer programming μΣ会é\r\nKW - Computer programming\r\nKW - Computer algorithms\r\nER - \r\n|; + + my $output; + $tt->process( $template_filepath, { test => 'pouet' }, \$output ); + + %mail = $email->fill_body_for_sending( + { + template => $output, + default_filename => 'myfile.ris', + attachment => $ris_attachment, + } + ); + + is ($mail{From}, $from, 'From is still set correctly'); + like( $mail{Subject}, qr{$subject}, ); + + my $encoded_header = encode_qp($header); + my $encoded_message = encode_qp($header); + my $encoded_ris_attachment = encode_base64(Encode::encode('UTF-8', $ris_attachment)); + like( $mail{body}, qr{$encoded_header}, ); + like( $mail{body}, qr{$encoded_message}, ); + like( $mail{body}, qr{$encoded_ris_attachment}, ); +}; diff --git a/t/data/templates/send_by_email.tt b/t/data/templates/send_by_email.tt new file mode 100644 index 0000000..9cbd611 --- /dev/null +++ b/t/data/templates/send_by_email.tt @@ -0,0 +1,11 @@ + +My subject μΣ会é + + +
    +My header μΣ会é + + + +My Message μΣ会é + diff --git a/t/db_dependent/Biblio/BuildBiblioDataForExport.t b/t/db_dependent/Biblio/BuildBiblioDataForExport.t new file mode 100644 index 0000000..238c4f8 --- /dev/null +++ b/t/db_dependent/Biblio/BuildBiblioDataForExport.t @@ -0,0 +1,139 @@ +use Modern::Perl; +use Test::More tests => 4; + +use Test::MockModule; +use MARC::Record; +use MARC::Field; + +use C4::Biblio; +use C4::Context; +use C4::Items; +use C4::Record; +use Koha::DateUtils; + +my $dbh = C4::Context->dbh; +$dbh->{AutoCommit} = 0; +$dbh->{RaiseError} = 1; + +my $module_biblio = Test::MockModule->new('C4::Biblio'); + +#my $title = q|The art of computer programming μΣ会é|; +my $title = q|The art of computer programming|; +my $record = new_record(); +my ( $biblionumber, $biblioitemnumber ) = AddBiblio( $record, q|| ); +AddItem({ homebranch => 'CPL', holdingbranch => 'CPL', itype => 'CANNOT', barcode => 'my new barcode' }, $biblionumber); + +subtest 'csv' => sub { + plan tests => 1; + my $csv_content = q(Title=245$a|Author=245$c|Subject=650$a); + my $csv_profile_id = insert_csv_profile({ csv_content => $csv_content }); + + my $csv_data = C4::Biblio::BuildBiblioDataForExport({ + biblionumbers => [ $biblionumber ], + format => 'csv', + csv_profile_id => $csv_profile_id, + }); + + is_deeply( $csv_data, { records_data => [], records_file => qq{Title|Author|Subject +"$title,The art of another title"|"Donald E. Knuth.,Donald E. Knuth. II"|"Computer programming.,Computer algorithms." +}}, 'BuildBiblioDataForExport should return correct values in csv' ); +}; + +subtest 'iso2709' => sub { + plan tests => 7; + my $iso2709_data = C4::Biblio::BuildBiblioDataForExport({ + biblionumbers => [ $biblionumber ], + format => 'iso2709', + }); + + my $today = output_pref({ dt => dt_from_string, dateformat => 'iso', dateonly => 1}); + + like( $iso2709_data->{records_file}, qr{00467nam a2200121 a \d+140211b xxu||||| |||| 00| 0 eng d1 aKnuth, Donald Ervind193814a$titlecDonald E. Knuth.9014aThe art of another titlecDonald E. Knuth. II91 1aComputer programming.9462 0aComputer algorithms.9499 c57d57 00104070910aCPLbCPLd$todaypmy new barcoder$todayw$todayyCANNOT}, 'BuildBiblioDataForExport should return a correct records file in iso2709' ); + + my $first_biblio_data = @{ $iso2709_data->{records_data} }[0]; + is( $first_biblio_data->{HASAUTHORS}, 1 ); + is( scalar( @{ $first_biblio_data->{MARCSUBJCTS} } ), 2, '499 and 462' ); + is( $first_biblio_data->{title}, qq{$title | The art of another title}, ); + is( scalar( @{ $first_biblio_data->{ITEM_RESULTS} } ), 1, '1 item' ); + is( scalar( @{ $first_biblio_data->{MARCAUTHORS} } ), 0, '0 author' ); # Could be fixed if needed + is( $first_biblio_data->{biblionumber}, $biblionumber, 'bibionumber is correct' ); +}; + +subtest 'ris' => sub { + plan tests => 1; + my $ris_data = C4::Biblio::BuildBiblioDataForExport({ + biblionumbers => [ $biblionumber ], + format => 'ris', + }); + is( $ris_data->{records_file}, qq|TY - BOOK\r\nAU - Knuth, Donald Ervin\r\nTI - $title\r\nKW - Computer programming\r\nKW - Computer algorithms\r\nER - \r\n|,); +}; + +subtest 'bibtex' => sub { + plan tests => 1; + my $bibtex_data = C4::Biblio::BuildBiblioDataForExport({ + biblionumbers => [ $biblionumber ], + format => 'bibtex', + }); + is( $bibtex_data->{records_file}, qq|\@book{$biblionumber, + author = {Knuth, Donald Ervin}, + title = {The art of computer programming} +} +|); +}; + +sub insert_csv_profile { + my ( $params ) = @_; + $dbh->do(q| + INSERT INTO export_format(profile, description, content, csv_separator, field_separator, subfield_separator, encoding, type) VALUES (?, ?, ?, ?, ?, ?, ?, ?) + |, {}, ("TEST_PROFILE4", "my desc", $params->{csv_content}, '|', ';', ',', 'utf8', 'marc') + ); + return $dbh->last_insert_id( undef, undef, 'export_format', undef ); +} + +sub new_record { + my $record = MARC::Record->new; + $record->leader('03174nam a2200445 a 4500'); + my @fields = ( + MARC::Field->new( + '008', "140211b xxu||||| |||| 00| 0 eng d" + ), + MARC::Field->new( + 100, '1', ' ', + a => 'Knuth, Donald Ervin', + d => '1938', + ), + MARC::Field->new( + 245, '1', '4', + a => $title, + c => 'Donald E. Knuth.', + 9 => '0', + ), + MARC::Field->new( + 245, '1', '4', + a => 'The art of another title', + c => 'Donald E. Knuth. II', + 9 => '1', + ), + MARC::Field->new( + 650, ' ', '1', + a => 'Computer programming.', + 9 => '462', + ), + MARC::Field->new( + 650, ' ', '0', + a => 'Computer algorithms.', + 9 => '499', + ), + MARC::Field->new( + 952, ' ', ' ', + p => '3010023917', + y => 'BK', + c => 'GEN', + d => '2001-06-25', + ), + ); + $record->append_fields(@fields); + return $record; +} + +done_testing; diff --git a/virtualshelves/downloadshelf.pl b/virtualshelves/downloadshelf.pl index 5a00694..bcfd63e 100755 --- a/virtualshelves/downloadshelf.pl +++ b/virtualshelves/downloadshelf.pl @@ -21,7 +21,6 @@ use strict; use warnings; use CGI qw ( -utf8 ); -use Encode qw(encode); use C4::Auth; use C4::Biblio; diff --git a/virtualshelves/sendshelf.pl b/virtualshelves/sendshelf.pl index cb46ce2..91bf97d 100755 --- a/virtualshelves/sendshelf.pl +++ b/virtualshelves/sendshelf.pl @@ -17,20 +17,17 @@ # You should have received a copy of the GNU General Public License # along with Koha; if not, see . -use strict; -use warnings; +use Modern::Perl; use CGI qw ( -utf8 ); -use Encode qw( encode ); use Carp; use Mail::Sendmail; -use MIME::QuotedPrint; -use MIME::Base64; use C4::Auth; use C4::Biblio; use C4::Items; use C4::Output; +use C4::Csv qw( GetCsvProfilesLoop ); use Koha::Email; use Koha::Virtualshelves; @@ -48,6 +45,7 @@ my ( $template, $borrowernumber, $cookie ) = get_template_and_user( my $shelfid = $query->param('shelfid'); my $email = $query->param('email'); +my $format = $query->param('format') || 'iso2709'; my $dbh = C4::Context->dbh; @@ -70,97 +68,41 @@ if ($email) { } ); - my $shelf = Koha::Virtualshelves->find( $shelfid ); - my $contents = $shelf->get_contents; - my $marcflavour = C4::Context->preference('marcflavour'); - my $iso2709; - my @results; - - while ( my $content = $contents->next ) { - my $biblionumber = $content->biblionumber->biblionumber; - my $fw = GetFrameworkCode($biblionumber); - my $dat = GetBiblioData($biblionumber); - my $record = GetMarcBiblio($biblionumber, 1); - my $marcnotesarray = GetMarcNotes( $record, $marcflavour ); - my $marcauthorsarray = GetMarcAuthors( $record, $marcflavour ); - my $marcsubjctsarray = GetMarcSubjects( $record, $marcflavour ); - my $subtitle = GetRecordValue( 'subtitle', $record, $fw ); - - my @items = GetItemsInfo($biblionumber); - - $dat->{ISBN} = GetMarcISBN($record, $marcflavour); - $dat->{MARCNOTES} = $marcnotesarray; - $dat->{MARCSUBJCTS} = $marcsubjctsarray; - $dat->{MARCAUTHORS} = $marcauthorsarray; - $dat->{'biblionumber'} = $biblionumber; - $dat->{ITEM_RESULTS} = \@items; - $dat->{subtitle} = $subtitle; - $dat->{HASAUTHORS} = $dat->{'author'} || @$marcauthorsarray; - - $iso2709 .= $record->as_usmarc(); - - push( @results, $dat ); + my @shelf = GetShelf($shelfid); + my ( $items, $totitems ) = GetShelfContents($shelfid); + + my $csv_profile_id; + if ( $format =~ m|^\d+$| ) { + $csv_profile_id = $format; + $format = 'csv'; } + my @biblionumbers = map { $_->{biblionumber} } @$items; + my $data = C4::Biblio::BuildBiblioDataForExport( + { + biblionumbers => \@biblionumbers, + format => $format, + csv_profile_id => $csv_profile_id + } + ); + my $records_file = $data->{records_file}; + my $records_data = $data->{records_data}; $template2->param( - BIBLIO_RESULTS => \@results, + BIBLIO_RESULTS => $records_data, comment => $comment, shelfname => $shelf->shelfname, ); # Getting template result my $template_res = $template2->output(); - my $body; - - # Analysing information and getting mail properties - if ( $template_res =~ /(.*)/s ) { - $mail{'subject'} = Encode::encode("UTF-8", $1); - $mail{subject} =~ s|\n?(.*)\n?|$1|; - } - else { $mail{'subject'} = "no subject"; } - - my $email_header = ""; - if ( $template_res =~ /
    (.*)/s ) { - $email_header = $1; - $email_header =~ s|\n?(.*)\n?|$1|; - $email_header = encode_qp(Encode::encode("UTF-8", $email_header)); - } - - my $email_file = "list.txt"; - if ( $template_res =~ /(.*)/s ) { - $email_file = $1; - $email_file =~ s|\n?(.*)\n?|$1|; - } - if ( $template_res =~ /(.*)/s ) { - $body = $1; - $body =~ s|\n?(.*)\n?|$1|; - $body = encode_qp(Encode::encode("UTF-8", $body)); - } - - my $boundary = "====" . time() . "===="; - - # We set and put the multipart content - $mail{'content-type'} = "multipart/mixed; boundary=\"$boundary\""; - - my $isofile = encode_base64( encode( "UTF-8", $iso2709 ) ); - $boundary = '--' . $boundary; - - $mail{body} = <fill_body_for_sending( + { + template => $template_res, + default_filename => "list.$format", + attachment => $records_file, + } + ); # Sending mail if ( sendmail %mail ) { @@ -182,6 +124,7 @@ else { $template->param( shelfid => $shelfid, url => "/cgi-bin/koha/virtualshelves/sendshelf.pl", + csv_profiles => GetCsvProfilesLoop('marc'), ); output_html_with_http_headers $query, $cookie, $template->output; } -- 1.9.1