X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=opac%2Fopac-tags.pl;h=272d896f2367e738f67f29b479fefb36f552b39f;hb=6d3136c7e893011bd7cdfd0b6415d20929b6a66b;hp=3d5d5ddd89beabb1792b19723097b16b4c2fc474;hpb=f5b7246ed8afde2ed87e4db5248715187d9a8b8c;p=koha.git diff --git a/opac/opac-tags.pl b/opac/opac-tags.pl index 3d5d5ddd89..272d896f23 100755 --- a/opac/opac-tags.pl +++ b/opac/opac-tags.pl @@ -4,21 +4,25 @@ # # This file is part of Koha. # -# Koha is free software; you can redistribute it and/or modify it under the -# terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. +# Koha is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. # -# Koha is distributed in the hope that it will be useful, but WITHOUT ANY -# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# Koha is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. # -# You should have received a copy of the GNU General Public License along with -# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place, -# Suite 330, Boston, MA 02111-1307 USA +# You should have received a copy of the GNU General Public License +# along with Koha; if not, see . -=head1 +=head1 NAME + +opac-tags.pl + +=head1 DESCRIPTION TODO :: Description here @@ -26,37 +30,46 @@ C4::Scrubber is used to remove all markup content from the sumitted text. =cut -use strict; -use warnings; -use CGI; +use Modern::Perl; + +use CGI qw ( -utf8 ); use CGI::Cookie; # need to check cookies before having CGI parse the POST request use C4::Auth qw(:DEFAULT check_cookie_auth); use C4::Context; use C4::Debug; -use C4::Output 3.02 qw(:html :ajax pagination_bar); -use C4::Dates qw(format_date); +use C4::Output qw(:html :ajax pagination_bar); use C4::Scrubber; use C4::Biblio; -use C4::Tags qw(add_tag get_approval_rows get_tag_rows remove_tag); +use C4::Items qw(GetItemsInfo GetHiddenItemnumbers); +use C4::Tags qw(add_tag get_approval_rows get_tag_rows remove_tag stratify_tags); +use C4::XSLT; + +use Data::Dumper; + +use Koha::Biblios; my %newtags = (); my @deltags = (); my %counts = (); my @errors = (); +my $perBibResults = {}; -sub ajax_auth_cgi ($) { # returns CGI object - my $needed_flags = shift; - my %cookies = fetch CGI::Cookie; +# Indexes of @errors that do not apply to a particular biblionumber. +my @globalErrorIndexes = (); + +sub ajax_auth_cgi { # returns CGI object + my $needed_flags = shift; + my %cookies = CGI::Cookie->fetch; my $input = CGI->new; - my $sessid = $cookies{'CGISESSID'}->value || $input->param('CGISESSID'); + my $sessid = $cookies{'CGISESSID'}->value; my ($auth_status, $auth_sessid) = check_cookie_auth($sessid, $needed_flags); $debug and print STDERR "($auth_status, $auth_sessid) = check_cookie_auth($sessid," . Dumper($needed_flags) . ")\n"; if ($auth_status ne "ok") { - output_ajax_with_http_headers $input, + output_with_http_headers $input, undef, "window.alert('Your CGI session cookie ($sessid) is not current. " . - "Please refresh the page and try again.');\n"; + "Please refresh the page and try again.');\n", 'js'; exit 0; } $debug and print STDERR "AJAX request: " . Dumper($input), @@ -75,6 +88,7 @@ my $openadds = C4::Context->preference('TagsModeration') ? 0 : 1; my $query = ($is_ajax) ? &ajax_auth_cgi({}) : CGI->new(); unless (C4::Context->preference('TagsEnabled')) { push @errors, {+ tagsdisabled=>1 }; + push @globalErrorIndexes, $#errors; } else { foreach ($query->param) { if (/^newtag(.*)/) { @@ -82,6 +96,7 @@ unless (C4::Context->preference('TagsEnabled')) { unless ($biblionumber =~ /^\d+$/) { $debug and warn "$_ references non numerical biblionumber '$biblionumber'"; push @errors, {+'badparam' => $_ }; + push @globalErrorIndexes, $#errors; next; } $newtags{$biblionumber} = $query->param($_); @@ -98,17 +113,18 @@ if ($is_ajax) { $debug and print STDERR "op: $loggedinuser\n"; } else { ($template, $loggedinuser, $cookie) = get_template_and_user({ - template_name => "opac-tags.tmpl", - query => $query, - type => "opac", - authnotrequired => ($add_op ? 0 : 1), # auth required to add tags - debug => 1, + template_name => "opac-tags.tt", + query => $query, + type => "opac", + authnotrequired => ($add_op ? 0 : 1), # auth required to add tags + debug => 1, }); } if ($add_op) { unless ($loggedinuser) { push @errors, {+'login' => 1 }; + push @globalErrorIndexes, $#errors; %newtags=(); # zero out any attempted additions @deltags=(); # zero out any attempted deletions } @@ -119,6 +135,7 @@ my @newtags_keys = (keys %newtags); if (scalar @newtags_keys) { $scrubber = C4::Scrubber->new(); foreach my $biblionumber (@newtags_keys) { + my $bibResults = {adds=>0, errors=>[]}; my @values = split /[;,]/, $newtags{$biblionumber}; foreach (@values) { s/^\s*(.+)\s*$/$1/; @@ -126,8 +143,10 @@ if (scalar @newtags_keys) { unless ($clean_tag eq $_) { if ($clean_tag =~ /\S/) { push @errors, {scrubbed=>$clean_tag}; + push @{$bibResults->{errors}}, {scrubbed=>$clean_tag}; } else { push @errors, {scrubbed_all_bad=>1}; + push @{$bibResults->{errors}}, {scrubbed_all_bad=>1}; next; # we don't add it if there's nothing left! } } @@ -136,11 +155,14 @@ if (scalar @newtags_keys) { add_tag($biblionumber,$clean_tag,$loggedinuser) ; if ($result) { $counts{$biblionumber}++; + $bibResults->{adds}++; } else { push @errors, {failed_add_tag=>$clean_tag}; - warn "add_tag($biblionumber,$clean_tag,$loggedinuser...) returned bad result (" . (defined $result ? $result : 'UNDEF') .")"; + push @{$bibResults->{errors}}, {failed_add_tag=>$clean_tag}; + $debug and warn "add_tag($biblionumber,$clean_tag,$loggedinuser...) returned bad result (" . (defined $result ? $result : 'UNDEF') .")"; } } + $perBibResults->{$biblionumber} = $bibResults; } } my $dels = 0; @@ -156,6 +178,19 @@ if ($is_ajax) { my $sum = 0; foreach (values %counts) {$sum += $_;} my $js_reply = sprintf("response = {\n\tadded: %d,\n\tdeleted: %d,\n\terrors: %d",$sum,$dels,scalar @errors); + + # If no add attempts were made, flag global errors. + if (@globalErrorIndexes) { + $js_reply .= ",\n\tglobal_errors: ["; + my $first = 1; + foreach (@globalErrorIndexes) { + $js_reply .= "," unless $first; + $first = 0; + $js_reply .= "\n\t\t$_"; + } + $js_reply .= "\n\t]"; + } + my $err_string = ''; if (scalar @errors) { $err_string = ",\n\talerts: ["; # open response_function @@ -168,28 +203,83 @@ if ($is_ajax) { } $err_string .= "\n\t]\n"; # close response_function } - output_ajax_with_http_headers($query, "$js_reply\n$err_string};"); + + # Add per-biblionumber results for use on results page + my $js_perbib = ""; + for my $bib (keys %$perBibResults) { + my $bibResult = $perBibResults->{$bib}; + my $js_bibres = ",\n\t$bib: {\n\t\tadded: $bibResult->{adds}"; + $js_bibres .= ",\n\t\terrors: ["; + my $i = 0; + foreach (@{$bibResult->{errors}}) { + $js_bibres .= "," if ($i); + my $key = (keys %$_)[0]; + $js_bibres .= "\n\t\t\t KOHA.Tags.tag_message.$key(\"" . $_->{$key} . '")'; + $i++; + } + $js_bibres .= "\n\t\t]\n\t}"; + $js_perbib .= $js_bibres; + } + + output_with_http_headers($query, undef, "$js_reply\n$err_string\n$js_perbib\n};", 'js'); exit; } my $results = []; my $my_tags = []; +my $borcat = q{}; -if ($loggedinuser and not $query->param('hidemytags')) { - $my_tags = get_tag_rows({borrowernumber=>$loggedinuser}); - foreach (@$my_tags) { - my $biblio = GetBiblioData($_->{biblionumber}); - $_->{bib_summary} = $biblio->{title}; - ($biblio->{author}) and $_->{bib_summary} .= " by " . $biblio->{author}; - my $date = $_->{date_created} || ''; - $date =~ /\s+(\d{2}\:\d{2}\:\d{2})/; - $_->{time_created_display} = $1; - $_->{date_created_display} = format_date($_->{date_created}); - } +if ($loggedinuser) { + my $patron = Koha::Patrons->find( { borrowernumber => $loggedinuser } ); + $borcat = $patron ? $patron->categorycode : $borcat; + my $should_hide = C4::Context->preference('OpacHiddenItems') // q{}; + $should_hide = ( $should_hide =~ /\S/ ) ? 1 : 0; + $my_tags = get_tag_rows({borrowernumber=>$loggedinuser}); + my $my_approved_tags = get_approval_rows({ approved => 1 }); + foreach my $tag (@$my_tags) { + $tag->{visible} = 0; + my $biblio = Koha::Biblios->find( $tag->{biblionumber} ); + my $record = &GetMarcBiblio({ + biblionumber => $tag->{biblionumber}, + embed_items => 1, + opac => 1, + borcat => $borcat }); + next unless $record; + my $hidden_items = undef; + my @hidden_itemnumbers; + my @all_items; + if ($should_hide) { + @all_items = GetItemsInfo( $tag->{biblionumber} ); + @hidden_itemnumbers = GetHiddenItemnumbers({ + items => \@all_items, + borcat => $borcat }); + $hidden_items = \@hidden_itemnumbers; + } + next if ( $should_hide && scalar @all_items == scalar @hidden_itemnumbers ); + $tag->{subtitle} = GetRecordValue( 'subtitle', $record, GetFrameworkCode( $tag->{biblionumber} ) ); + $tag->{title} = $biblio->title; + $tag->{author} = $biblio->author; + + my $xslfile = C4::Context->preference('OPACXSLTResultsDisplay'); + my $lang = $xslfile ? C4::Languages::getlanguage() : undef; + my $sysxml = $xslfile ? C4::XSLT::get_xslt_sysprefs() : undef; + + if ( $xslfile ) { + $tag->{XSLTBloc} = XSLTParse4Display( + $tag->{ biblionumber }, $record, "OPACXSLTResultsDisplay", + 1, $hidden_items, $sysxml, $xslfile, $lang + ); + } + + my $date = $tag->{date_created} || ''; + $date =~ /\s+(\d{2}\:\d{2}\:\d{2})/; + $tag->{time_created_display} = $1; + $tag->{approved} = ( grep { $_->{term} eq $tag->{term} and $_->{approved} } @$my_approved_tags ); + $tag->{visible} = 1; + } } -$template->param(tagsview => 1, -dateformat => C4::Context->preference("dateformat")); +$template->param(tagsview => 1); if ($add_op) { my $adds = 0; @@ -200,12 +290,14 @@ if ($add_op) { deleted_count => $dels, ); } else { - my ($arg,$limit); + my ($arg,$limit,$mine); my $hardmax = 100; # you might disagree what this value should be, but there definitely should be a max $limit = $query->param('limit') || $hardmax; + $mine = $query->param('mine') || 0; # set if the patron want to see only his own tags. ($limit =~ /^\d+$/ and $limit <= $hardmax) or $limit = $hardmax; $template->param(limit => $limit); my $arghash = {approved=>1, limit=>$limit, 'sort'=>'-weight_total'}; + $arghash->{'borrowernumber'} = $loggedinuser if $mine; # ($openadds) or $arghash->{approved} = 1; if ($arg = $query->param('tag')) { $arghash->{term} = $arg; @@ -213,38 +305,31 @@ if ($add_op) { $arghash->{biblionumber} = $arg; } $results = get_approval_rows($arghash); - + my @filtered_results; + foreach my $my_tag (@$my_tags) { + if (grep { $_->{term} eq $my_tag->{term} } @$results) { + if (! $my_tag->{visible} ) { + my $check_biblio = GetMarcBiblio({ + biblionumber => $my_tag->{biblionumber}, + embed_items => 1, + opac => 1, + borcat => $borcat }); + if ($check_biblio) { + push @filtered_results, $my_tag; + } + } else { + push @filtered_results, $my_tag; + } + } + } + $results = \@filtered_results; + stratify_tags(10, $results); # work out the differents sizes for things my $count = scalar @$results; - $template->param(TAGLOOP_COUNT => $count); - # Here we make a halfhearted attempt to separate the tags into "strata" based on weight_total - # FIXME: code4lib probably has a better algorithm, iirc - # FIXME: when we get a better algorithm, move to C4 - my $maxstrata = 5; - my $strata = 1; - my $previous = 0; - my $chunk = ($count/$maxstrata)/2; - my $total = 0; - my %cloud; - foreach (reverse @$results) { - my $current = $_->{weight_total}; - $total++; - $cloud{$strata}++; - if ($current == $previous) { - $_->{cloudweight} = $strata; - next; - } - if ($strata < $maxstrata and - ($cloud{$strata} > $chunk or - $count-$total <= $maxstrata-$strata)) { - $strata++; - } - $_->{cloudweight} = $strata; - $previous = $current; - } + $template->param(TAGLOOP_COUNT => $count, mine => $mine); } -$query->param('hidemytags') and $template->param(hidemytags => 1); (scalar @errors ) and $template->param(ERRORS => \@errors); -(scalar @$results) and $template->param(TAGLOOP => $results); +my @orderedresult = sort { uc($a->{'term'}) cmp uc($b->{'term'}) } @$results; +(scalar @$results) and $template->param(TAGLOOP => \@orderedresult ); (scalar @$my_tags) and $template->param(MY_TAGS => $my_tags); output_html_with_http_headers $query, $cookie, $template->output;