From e2c410ca462b4de39d8084302a9552ddcd94bc71 Mon Sep 17 00:00:00 2001 From: Nick Clemens Date: Thu, 14 Apr 2022 12:20:09 +0000 Subject: [PATCH] Bug 30528: Process limits before handling CCL query This patch moves the code that handles limit processing before that for CCL queries to ensure that special limit cases (branch, multibranch, etc) are handled before adding the limits to the query string To test: 1 - Apply unit tests patch only 2 - prove -v t/db_dependent/Search.t 3 - It fails 4 - Apply this patch 5 - It passes! 6 - Test searching and confirm things work as epxected Signed-off-by: Martin Renvoize --- C4/Search.pm | 182 +++++++++++++++++++++++++-------------------------- 1 file changed, 91 insertions(+), 91 deletions(-) diff --git a/C4/Search.pm b/C4/Search.pm index 5842b0e6cc..484d9471d8 100644 --- a/C4/Search.pm +++ b/C4/Search.pm @@ -1231,25 +1231,104 @@ sub buildQuery { $query = "ccl=$query" if $cclq; } + # add limits + my %group_OR_limits; + my $availability_limit; + foreach my $this_limit (@limits) { + next unless $this_limit; + if ( $this_limit =~ /available/ ) { +# +## 'available' is defined as (items.onloan is NULL) and (items.itemlost = 0) +## In English: +## all records not indexed in the onloan register (zebra) and all records with a value of lost equal to 0 + $availability_limit .= +"( (allrecords,AlwaysMatches='') and (not-onloan-count,st-numeric >= 1) and (lost,st-numeric=0) )"; + $limit_cgi .= "&limit=available"; + $limit_desc .= ""; + } + + # group_OR_limits, prefixed by mc- + # OR every member of the group + elsif ( $this_limit =~ /mc/ ) { + my ($k,$v) = split(/:/, $this_limit,2); + if ( $k !~ /mc-i(tem)?type/ ) { + # in case the mc-ccode value has complicating chars like ()'s inside it we wrap in quotes + $this_limit =~ tr/"//d; + $this_limit = $k.':"'.$v.'"'; + } + + $group_OR_limits{$k} .= " or " if $group_OR_limits{$k}; + $limit_desc .= " or " if $group_OR_limits{$k}; + $group_OR_limits{$k} .= "$this_limit"; + $limit_cgi .= "&limit=" . uri_escape_utf8($this_limit); + $limit_desc .= " $this_limit"; + } + elsif ( $this_limit =~ '^multibranchlimit:|^branch:' ) { + $limit_cgi .= "&limit=" . uri_escape_utf8($this_limit); + $limit .= " and " if $limit || $query; + my $branchfield = C4::Context->preference('SearchLimitLibrary'); + my @branchcodes; + if( $this_limit =~ '^multibranchlimit:' ){ + my ($group_id) = ( $this_limit =~ /^multibranchlimit:(.*)$/ ); + my $search_group = Koha::Library::Groups->find( $group_id ); + @branchcodes = map { $_->branchcode } $search_group->all_libraries; + @branchcodes = sort { $a cmp $b } @branchcodes; + } else { + @branchcodes = ( $this_limit =~ /^branch:(.*)$/ ); + } + + if (@branchcodes) { + if ( $branchfield eq "homebranch" ) { + $this_limit = sprintf "(%s)", join " or ", map { 'homebranch: ' . $_ } @branchcodes; + } + elsif ( $branchfield eq "holdingbranch" ) { + $this_limit = sprintf "(%s)", join " or ", map { 'holdingbranch: ' . $_ } @branchcodes; + } + else { + $this_limit = sprintf "(%s or %s)", + join( " or ", map { 'homebranch: ' . $_ } @branchcodes ), + join( " or ", map { 'holdingbranch: ' . $_ } @branchcodes ); + } + } + $limit .= "$this_limit"; + $limit_desc .= " $this_limit"; + } elsif ( $this_limit =~ '^search_filter:' ) { + $limit_cgi .= "&limit=" . uri_escape_utf8($this_limit); + my ($filter_id) = ( $this_limit =~ /^search_filter:(.*)$/ ); + my $search_filter = Koha::SearchFilters->find( $filter_id ); + next unless $search_filter; + my $expanded = $search_filter->expand_filter; + my ( $error, undef, undef, undef, undef, $fixed_limit, undef, undef, undef ) = buildQuery ( undef, undef, undef, $expanded, undef, undef, $lang); + $limit .= " and " if $limit || $query; + $limit .= "$fixed_limit"; + $limit_desc .= " $limit"; + } + + # Regular old limits + else { + $limit .= " and " if $limit || $query; + $limit .= "$this_limit"; + $limit_cgi .= "&limit=" . uri_escape_utf8($this_limit); + $limit_desc .= " $this_limit"; + } + } + foreach my $k (keys (%group_OR_limits)) { + $limit .= " and " if ( $query || $limit ); + $limit .= "($group_OR_limits{$k})"; + } + if ($availability_limit) { + $limit .= " and " if ( $query || $limit ); + $limit .= "($availability_limit)"; + } + # for handling ccl, cql, pqf queries in diagnostic mode, skip the rest of the steps # DIAGNOSTIC ONLY!! if ( $query =~ /^ccl=/ ) { my $q=$'; # This is needed otherwise ccl= and &limit won't work together, and # this happens when selecting a subject on the opac-detail page - @limits = grep {!/^$/} @limits; my $original_q = $q; # without available part - unless ( grep { $_ eq 'available' } @limits ) { - $q =~ s| and \( \(allrecords,AlwaysMatches=''\) and \(not-onloan-count,st-numeric >= 1\) and \(lost,st-numeric=0\) \)||; - $original_q = $q; - } - if ( @limits ) { - if ( grep { $_ eq 'available' } @limits ) { - $q .= q| and ( (allrecords,AlwaysMatches='') and (not-onloan-count,st-numeric >= 1) and (lost,st-numeric=0) )|; - @limits = grep {!/^available$/} @limits; - } - $q .= ' and '.join(' and ', @limits) if @limits; - } + $q .= $limit; return ( undef, $q, $q, "q=ccl=".uri_escape_utf8($q), $original_q, '', '', '', 'ccl' ); } if ( $query =~ /^cql=/ ) { @@ -1446,85 +1525,6 @@ sub buildQuery { } Koha::Logger->get->debug("QUERY BEFORE LIMITS: >$query<"); - # add limits - my %group_OR_limits; - my $availability_limit; - foreach my $this_limit (@limits) { - next unless $this_limit; - if ( $this_limit =~ /available/ ) { -# -## 'available' is defined as (items.onloan is NULL) and (items.itemlost = 0) -## In English: -## all records not indexed in the onloan register (zebra) and all records with a value of lost equal to 0 - $availability_limit .= -"( (allrecords,AlwaysMatches='') and (not-onloan-count,st-numeric >= 1) and (lost,st-numeric=0) )"; - $limit_cgi .= "&limit=available"; - $limit_desc .= ""; - } - - # group_OR_limits, prefixed by mc- - # OR every member of the group - elsif ( $this_limit =~ /mc/ ) { - my ($k,$v) = split(/:/, $this_limit,2); - if ( $k !~ /mc-i(tem)?type/ ) { - # in case the mc-ccode value has complicating chars like ()'s inside it we wrap in quotes - $this_limit =~ tr/"//d; - $this_limit = $k.':"'.$v.'"'; - } - - $group_OR_limits{$k} .= " or " if $group_OR_limits{$k}; - $limit_desc .= " or " if $group_OR_limits{$k}; - $group_OR_limits{$k} .= "$this_limit"; - $limit_cgi .= "&limit=" . uri_escape_utf8($this_limit); - $limit_desc .= " $this_limit"; - } - elsif ( $this_limit =~ '^multibranchlimit:|^branch:' ) { - $limit_cgi .= "&limit=" . uri_escape_utf8($this_limit); - $limit .= " and " if $limit || $query; - my $branchfield = C4::Context->preference('SearchLimitLibrary'); - my @branchcodes; - if( $this_limit =~ '^multibranchlimit:' ){ - my ($group_id) = ( $this_limit =~ /^multibranchlimit:(.*)$/ ); - my $search_group = Koha::Library::Groups->find( $group_id ); - @branchcodes = map { $_->branchcode } $search_group->all_libraries; - @branchcodes = sort { $a cmp $b } @branchcodes; - } else { - @branchcodes = ( $this_limit =~ /^branch:(.*)$/ ); - } - - if (@branchcodes) { - if ( $branchfield eq "homebranch" ) { - $this_limit = sprintf "(%s)", join " or ", map { 'homebranch: ' . $_ } @branchcodes; - } - elsif ( $branchfield eq "holdingbranch" ) { - $this_limit = sprintf "(%s)", join " or ", map { 'holdingbranch: ' . $_ } @branchcodes; - } - else { - $this_limit = sprintf "(%s or %s)", - join( " or ", map { 'homebranch: ' . $_ } @branchcodes ), - join( " or ", map { 'holdingbranch: ' . $_ } @branchcodes ); - } - } - $limit .= "$this_limit"; - $limit_desc .= " $this_limit"; - } - - # Regular old limits - else { - $limit .= " and " if $limit || $query; - $limit .= "$this_limit"; - $limit_cgi .= "&limit=" . uri_escape_utf8($this_limit); - $limit_desc .= " $this_limit"; - } - } - foreach my $k (keys (%group_OR_limits)) { - $limit .= " and " if ( $query || $limit ); - $limit .= "($group_OR_limits{$k})"; - } - if ($availability_limit) { - $limit .= " and " if ( $query || $limit ); - $limit .= "($availability_limit)"; - } # Normalize the query and limit strings # This is flawed , means we can't search anything with : in it -- 2.20.1