Bug 17600: Standardize our EXPORT_OK
[srvgit] / opac / opac-tags.pl
index 0953f82..df323ce 100755 (executable)
@@ -4,18 +4,18 @@
 #
 # 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.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+# You should have received a copy of the GNU General Public License
+# along with Koha; if not, see <http://www.gnu.org/licenses>.
 
 
 =head1 NAME
@@ -30,18 +30,30 @@ 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::Auth qw( check_cookie_auth get_template_and_user );
 use C4::Context;
-use C4::Debug;
-use C4::Output 3.02 qw(:html :ajax pagination_bar);
+use C4::Output qw( output_with_http_headers is_ajax output_html_with_http_headers );
 use C4::Scrubber;
-use C4::Biblio;
-use C4::Tags qw(add_tag get_approval_rows get_tag_rows remove_tag);
+use C4::Biblio qw( GetMarcBiblio );
+use C4::Items qw( GetHiddenItemnumbers GetItemsInfo );
+use C4::Tags qw(
+    add_tag
+    get_approval_rows
+    get_tag_rows
+    remove_tag
+    stratify_tags
+);
+use C4::XSLT;
+
+
+use Koha::Logger;
+use Koha::Biblios;
+use Koha::CirculationRules;
 
 my %newtags = ();
 my @deltags = ();
@@ -52,22 +64,18 @@ my $perBibResults = {};
 # Indexes of @errors that do not apply to a particular biblionumber.
 my @globalErrorIndexes = ();
 
-sub ajax_auth_cgi ($) {     # returns CGI object
+sub ajax_auth_cgi {     # returns CGI object
        my $needed_flags = shift;
-       my %cookies = fetch CGI::Cookie;
+    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_with_http_headers $input, undef,
                "window.alert('Your CGI session cookie ($sessid) is not current.  " .
                "Please refresh the page and try again.');\n", 'js';
                exit 0;
        }
-       $debug and print STDERR "AJAX request: " . Dumper($input),
-               "\n(\$auth_status,\$auth_sessid) = ($auth_status,$auth_sessid)\n";
        return $input;
 }
 
@@ -80,41 +88,38 @@ sub ajax_auth_cgi ($) {     # returns CGI object
 my $is_ajax = is_ajax();
 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(.*)/) {
-                       my $biblionumber = $1;
-                       unless ($biblionumber =~ /^\d+$/) {
-                               $debug and warn "$_ references non numerical biblionumber '$biblionumber'";
-                               push @errors, {+'badparam' => $_ };
-                push @globalErrorIndexes, $#errors;
-                               next;
-                       }
-                       $newtags{$biblionumber} = $query->param($_);
-               } elsif (/^del(\d+)$/) {
-                       push @deltags, $1;
-               }
-       }
+foreach ($query->param) {
+    if (/^newtag(.*)/) {
+        my $biblionumber = $1;
+        unless ($biblionumber =~ /^\d+$/) {
+            push @errors, {+'badparam' => $_ };
+            push @globalErrorIndexes, $#errors;
+            next;
+        }
+        $newtags{$biblionumber} = $query->param($_);
+    } elsif (/^del(\d+)$/) {
+        push @deltags, $1;
+    }
 }
 
 my $add_op = (scalar(keys %newtags) + scalar(@deltags)) ? 1 : 0;
 my ($template, $loggedinuser, $cookie);
 if ($is_ajax) {
        $loggedinuser = C4::Context->userenv->{'number'};  # must occur AFTER auth
-       $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
        });
 }
 
+unless ( C4::Context->preference('TagsEnabled') ) {
+    print $query->redirect("/cgi-bin/koha/errors/404.pl");
+    exit;
+}
+
 if ($add_op) {
        unless ($loggedinuser) {
                push @errors, {+'login' => 1 };
@@ -153,7 +158,7 @@ if (scalar @newtags_keys) {
                        } else {
                                push @errors, {failed_add_tag=>$clean_tag};
                                push @{$bibResults->{errors}}, {failed_add_tag=>$clean_tag};
-                               $debug and warn "add_tag($biblionumber,$clean_tag,$loggedinuser...) returned bad result (" . (defined $result ? $result : 'UNDEF') .")";
+                Koha::Logger->get->warn("add_tag($biblionumber,$clean_tag,$loggedinuser...) returned bad result (" . (defined $result ? $result : 'UNDEF') .")");
                        }
                }
         $perBibResults->{$biblionumber} = $bibResults;
@@ -221,21 +226,95 @@ if ($is_ajax) {
 
 my $results = [];
 my $my_tags = [];
+my $borcat  = q{};
 
 if ($loggedinuser) {
-       $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;
-       }
+    my $patron = Koha::Patrons->find( { borrowernumber => $loggedinuser } );
+    $borcat = $patron ? $patron->categorycode : $borcat;
+    my $rules = C4::Context->yaml_preference('OpacHiddenItems');
+    my $should_hide = ( $rules ) ? 1 : 0;
+    $my_tags = get_tag_rows({borrowernumber=>$loggedinuser});
+    my $my_approved_tags = get_approval_rows({ approved => 1 });
+
+    my $art_req_itypes;
+    if( C4::Context->preference('ArticleRequests') ) {
+        $art_req_itypes = Koha::CirculationRules->guess_article_requestable_itemtypes({ $patron ? ( categorycode => $patron->categorycode ) : () });
+    }
+
+    # get biblionumbers stored in the cart
+    my @cart_list;
+
+    if($query->cookie("bib_list")){
+        my $cart_list = $query->cookie("bib_list");
+        @cart_list = split(/\//, $cart_list);
+    }
+
+    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 (
+            (
+                !$patron
+                or ( $patron and !$patron->category->override_hidden_items )
+            )
+            and $biblio->hidden_in_opac( { rules => $rules } )
+          );
+        $tag->{title} = $biblio->title;
+        $tag->{subtitle} = $biblio->subtitle;
+        $tag->{medium} = $biblio->medium;
+        $tag->{part_number} = $biblio->part_number;
+        $tag->{part_name} = $biblio->part_name;
+        $tag->{author} = $biblio->author;
+        # BZ17530: 'Intelligent' guess if result can be article requested
+        $tag->{artreqpossible} = ( $art_req_itypes->{ $tag->{itemtype} // q{} } || $art_req_itypes->{ '*' } ) ? 1 : q{};
+
+        my $xslfile = C4::Context->preference('OPACXSLTResultsDisplay');
+        my $lang   = $xslfile ? C4::Languages::getlanguage()  : undef;
+        my $sysxml = $xslfile ? C4::XSLT::get_xslt_sysprefs() : undef;
+
+        if ($xslfile) {
+            my $variables = {
+                anonymous_session => ($loggedinuser) ? 0 : 1
+            };
+            $tag->{XSLTBloc} = XSLTParse4Display(
+                $tag->{biblionumber},     $record,
+                "OPACXSLTResultsDisplay", 1,
+                $hidden_items,            $sysxml,
+                $xslfile,                 $lang,
+                $variables
+            );
+        }
+
+        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;
+        # while we're checking each line, see if item is in the cart
+        if ( grep {$_ eq $biblio->biblionumber} @cart_list) {
+            $tag->{incart} = 1;
+        }
+    }
 }
 
-$template->param(tagsview => 1,
-dateformat => C4::Context->preference("dateformat"));
+$template->param(tagsview => 1);
 
 if ($add_op) {
        my $adds = 0;
@@ -261,34 +340,9 @@ if ($add_op) {
                $arghash->{biblionumber} = $arg;
        }
        $results = get_approval_rows($arghash);
-
+    stratify_tags(10, $results); # work out the differents sizes for things
        my $count = scalar @$results;
        $template->param(TAGLOOP_COUNT => $count, mine => $mine);
-       # 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;
-       }
 }
 (scalar @errors  ) and $template->param(ERRORS  => \@errors);
 my @orderedresult = sort { uc($a->{'term'}) cmp uc($b->{'term'}) } @$results;