@@ -, +, @@ --- C4/Biblio.pm | 54 ++++++++++++++-------- C4/Items.pm | 35 ++++++++++---- C4/Search.pm | 2 +- installer/data/mysql/sysprefs.sql | 1 + .../prog/en/modules/admin/preferences/opac.pref | 3 ++ opac/opac-ISBDdetail.pl | 13 ++++-- opac/opac-MARCdetail.pl | 13 ++++-- opac/opac-basket.pl | 8 +++- opac/opac-detail.pl | 9 +++- opac/opac-downloadcart.pl | 17 ++++--- opac/opac-downloadshelf.pl | 8 +++- opac/opac-export.pl | 20 +++++--- opac/opac-search.pl | 3 ++ opac/opac-sendbasket.pl | 10 ++-- opac/opac-sendshelf.pl | 10 ++-- opac/opac-tags.pl | 23 +++++---- opac/opac-user.pl | 10 ++-- 17 files changed, 161 insertions(+), 78 deletions(-) --- a/C4/Biblio.pm +++ a/C4/Biblio.pm @@ -1111,10 +1111,11 @@ sub GetMarcSubfieldStructureFromKohaField { =head2 GetMarcBiblio my $record = GetMarcBiblio({ - biblionumber => $biblionumber, - embed_items => $embeditems, - opac => $opac, - borcat => $patron_category }); + biblionumber => $biblionumber, + embed_items => $embeditems, + opac => $opac, + borcat => $patron_category, + patron_branch => $patron_branch }); Returns MARC::Record representing a biblio record, or C if the biblionumber doesn't exist. @@ -1144,6 +1145,13 @@ If the OpacHiddenItemsExceptions system preference is set, this patron category can be used to make visible OPAC items which would be normally hidden. It only makes sense in combination both embed_items and opac values true. +=item C<$patron_branch> + +If the OpacHiddenItemsLocalExceptions system preference is +set, this patron branchcode can be used to make visible OPAC +items which would be normally hidden. It only makes sense in +combination both embed_items and opac values true. + =back =cut @@ -1156,10 +1164,11 @@ sub GetMarcBiblio { return; } - my $biblionumber = $params->{biblionumber}; - my $embeditems = $params->{embed_items} || 0; - my $opac = $params->{opac} || 0; - my $borcat = $params->{borcat} // q{}; + my $biblionumber = $params->{biblionumber}; + my $embeditems = $params->{embed_items} || 0; + my $opac = $params->{opac} || 0; + my $borcat = $params->{borcat} // q{}; + my $patron_branch = $params->{patron_branch} // q{}; if (not defined $biblionumber) { carp 'GetMarcBiblio called with undefined biblionumber'; @@ -1188,10 +1197,11 @@ sub GetMarcBiblio { C4::Biblio::_koha_marc_update_bib_ids( $record, $frameworkcode, $biblionumber, $biblioitemnumber ); C4::Biblio::EmbedItemsInMarcBiblio({ - marc_record => $record, - biblionumber => $biblionumber, - opac => $opac, - borcat => $borcat }) + marc_record => $record, + biblionumber => $biblionumber, + opac => $opac, + borcat => $borcat, + patron_branch => $patron_branch }) if ($embeditems); return $record; @@ -2771,10 +2781,12 @@ sub ModZebra { =head2 EmbedItemsInMarcBiblio EmbedItemsInMarcBiblio({ - marc_record => $marc, - biblionumber => $biblionumber, - item_numbers => $itemnumbers, - opac => $opac }); + marc_record => $marc, + biblionumber => $biblionumber, + item_numbers => $itemnumbers, + opac => $opac, + borcat => $patron_categorycode, + patron_branch => $patron_branch }); Given a MARC::Record object containing a bib record, modify it to include the items attached to it as 9XX @@ -2783,14 +2795,14 @@ if $itemnumbers is defined, only specified itemnumbers are embedded. If $opac is true, then opac-relevant suppressions are included. -If opac filtering will be done, borcat should be passed to properly -override if necessary. +If opac filtering will be done, borcat and patron_branch should +be passed to properly override if necessary. =cut sub EmbedItemsInMarcBiblio { my ($params) = @_; - my ($marc, $biblionumber, $itemnumbers, $opac, $borcat); + my ($marc, $biblionumber, $itemnumbers, $opac, $borcat, $patron_branch); $marc = $params->{marc_record}; if ( !$marc ) { carp 'EmbedItemsInMarcBiblio: No MARC record passed'; @@ -2800,6 +2812,7 @@ sub EmbedItemsInMarcBiblio { $itemnumbers = $params->{item_numbers}; $opac = $params->{opac}; $borcat = $params->{borcat} // q{}; + $patron_branch = $params->{patron_branch} // q{}; $itemnumbers = [] unless defined $itemnumbers; @@ -2831,7 +2844,8 @@ sub EmbedItemsInMarcBiblio { $opachiddenitems ? C4::Items::GetHiddenItemnumbers({ items => \@items2pass, - borcat => $borcat }) + borcat => $borcat, + patron_branch => $patron_branch }) : (); # Convert to a hash for quick searching my %hiddenitems = map { $_ => 1 } @hiddenitems; --- a/C4/Items.pm +++ a/C4/Items.pm @@ -1232,25 +1232,31 @@ sub get_hostitemnumbers_of { =head2 GetHiddenItemnumbers - my @itemnumbers_to_hide = GetHiddenItemnumbers({ items => \@items, borcat => $category }); + my @itemnumbers_to_hide = GetHiddenItemnumbers({\ + items => \@items,\ + borcat => $category,\ + patron_branch => $patron_branch }); -Given a list of items it checks which should be hidden from the OPAC given -the current configuration. Returns a list of itemnumbers corresponding to -those that should be hidden. Optionally takes a borcat parameter for certain borrower types -to be excluded +Given a list of items it checks which should be hidden +from the OPAC given the current configuration. Returns a +list of itemnumbers corresponding to those that should be +hidden. Optionally takes a borcat and patron_branch parameter +so certain borrowers can override this hidden functionality. =cut sub GetHiddenItemnumbers { my $params = shift; my $items = $params->{items}; - if (my $exceptions = C4::Context->preference('OpacHiddenItemsExceptions') and $params->{'borcat'}){ + my $patron_categorycode = $params->{borcat} // q{}; + if (my $exceptions = C4::Context->preference('OpacHiddenItemsExceptions') and $patron_categorycode){ foreach my $except (split(/\|/, $exceptions)){ - if ($params->{'borcat'} eq $except){ + if ($patron_categorycode eq $except){ return; # we don't hide anything for this borrower category } } } + my $patron_branch = $params->{'patron_branch'} // q{}; my @resultitems; my $yaml = C4::Context->preference('OpacHiddenItems'); @@ -1266,6 +1272,8 @@ sub GetHiddenItemnumbers { } my $dbh = C4::Context->dbh; + my $local_exceptions_string = C4::Context->preference('OpacHiddenItemsLocalExceptions') // q{}; + my @local_exceptions = split /\|/, $local_exceptions_string; # For each item foreach my $item (@$items) { @@ -1284,8 +1292,17 @@ sub GetHiddenItemnumbers { # If the results matches the values in the yaml file if (any { $val eq $_ } @{$hidingrules->{$field}}) { - # We add the itemnumber to the list - push @resultitems, $item->{'itemnumber'}; + # override for branch items for patrons of that branch? + my $override = 0; + if ( $patron_branch eq $item->{'homebranch'} && + any { /^$patron_categorycode$/ } @local_exceptions ) { + + $override = 1; + } + if ($override==0) { + # We add the itemnumber to the list + push @resultitems, $item->{'itemnumber'}; + } # If at least one rule matched for an item, no need to test the others last; --- a/C4/Search.pm +++ a/C4/Search.pm @@ -2082,7 +2082,7 @@ sub searchResults { next; } # hidden based on OpacHiddenItems syspref - my @hi = C4::Items::GetHiddenItemnumbers({ items=> [ $item ], borcat => $search_context->{category} }); + my @hi = C4::Items::GetHiddenItemnumbers({ items=> [ $item ], borcat => $search_context->{category}, patron_branch => $search_context->{patron_branch} }); if (scalar @hi) { push @hiddenitems, @hi; $hideatopac_count++; --- a/installer/data/mysql/sysprefs.sql +++ a/installer/data/mysql/sysprefs.sql @@ -355,6 +355,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('opacheader','','70|10','Add HTML to be included as a custom header in the OPAC','Textarea'), ('OpacHiddenItems','','','This syspref allows to define custom rules for hiding specific items at opac. See docs/opac/OpacHiddenItems.txt for more informations.','Textarea'), ('OpacHiddenItemsExceptions','',NULL,'List of borrower categories, separated by |, that can see items otherwise hidden by OpacHiddenItems','Textarea'), +('OpacHiddenItemsLocalExceptions','',NULL,"List of borrower categories, separated by |, that allows logged in patrons whose branch matches the item's homebranch to see what otherwise would be hidden by OpacHiddenItems",'Textarea'), ('OpacHighlightedWords','1','','If Set, then queried words are higlighted in OPAC','YesNo'), ('OPACHoldingsDefaultSortField','first_column','first_column|homebranch|holdingbranch','Default sort field for the holdings table at the OPAC','choice'), ('OPACHoldsIfAvailableAtPickup','1','','Allow to pickup up holds at libraries where the item is available','YesNo'), --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref @@ -595,6 +595,9 @@ OPAC: - pref: OpacHiddenItemsExceptions - List of borrower categories, separated by |, that can see items otherwise hidden by OpacHiddenItems - + - pref: OpacHiddenItemsLocalExceptions + - List of borrower categories, separated by |, that allows logged in patrons whose branch matches an item's homebranch to see items otherwise hidden by OpacHiddenItems + - - pref: OpacAllowPublicListCreation default: 1 choices: --- a/opac/opac-ISBDdetail.pl +++ a/opac/opac-ISBDdetail.pl @@ -80,15 +80,20 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user( my $patron = Koha::Patrons->find( $loggedinuser ); my $borcat = q{}; +my $patron_branch = q{}; if ( $patron && C4::Context->preference('OpacHiddenItemsExceptions') ) { $borcat = $patron->categorycode; } +if ( $patron && C4::Context->preference('OpacHiddenItemsLocalExceptions') ) { + $patron_branch = $patron->branchcode; +} my $record = GetMarcBiblio({ - biblionumber => $biblionumber, - embed_items => 1, - opac => 1, - borcat => $borcat }); + biblionumber => $biblionumber, + embed_items => 1, + opac => 1, + borcat => $borcat, + patron_branch => $patron_branch }); if ( ! $record ) { print $query->redirect("/cgi-bin/koha/errors/404.pl"); exit; --- a/opac/opac-MARCdetail.pl +++ a/opac/opac-MARCdetail.pl @@ -86,16 +86,21 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user( my $patron = Koha::Patrons->find( $loggedinuser ); my $borcat = q{}; +my $patron_branch = q{}; if ( C4::Context->preference('OpacHiddenItemsExceptions') ) { # we need to fetch the borrower info here, so we can pass the category $borcat = $patron ? $patron->categorycode : $borcat; } +if ( C4::Context->preference('OpacHiddenItemsLocalExceptions') ) { + $patron_branch = $patron ? $patron->branchcode : $patron_branch; +} my $record = GetMarcBiblio({ - biblionumber => $biblionumber, - embed_items => 1, - opac => 1, - borcat => $borcat }); + biblionumber => $biblionumber, + embed_items => 1, + opac => 1, + borcat => $borcat, + patron_branch => $patron_branch }); if ( ! $record ) { print $query->redirect("/cgi-bin/koha/errors/404.pl"); exit; --- a/opac/opac-basket.pl +++ a/opac/opac-basket.pl @@ -58,12 +58,16 @@ if (C4::Context->preference('TagsEnabled')) { } } +my $patron = Koha::Patrons->find($borrowernumber); my $borcat = q{}; +my $patron_branch = q{}; if ( C4::Context->preference('OpacHiddenItemsExceptions') ) { # we need to fetch the borrower info here, so we can pass the category - my $patron = Koha::Patrons->find($borrowernumber); $borcat = $patron ? $patron->categorycode : $borcat; } +if ( C4::Context->preference('OpacHiddenItemsLocalExceptions') ) { + $patron_branch = $patron ? $patron->branchcode : $patron_branch; +} my $record_processor = Koha::RecordProcessor->new({ filters => 'ViewPolicy' }); foreach my $biblionumber ( @bibs ) { @@ -92,7 +96,7 @@ foreach my $biblionumber ( @bibs ) { my @all_items = &GetItemsInfo( $biblionumber ); # determine which ones should be hidden / visible - my @hidden_items = GetHiddenItemnumbers({ items => \@all_items, borcat => $borcat }); + my @hidden_items = GetHiddenItemnumbers({ items => \@all_items, borcat => $borcat, patron_branch => $patron_branch }); # If every item is hidden, then the biblio should be hidden too. next if (scalar @all_items >= 1 && scalar @hidden_items == scalar @all_items); --- a/opac/opac-detail.pl +++ a/opac/opac-detail.pl @@ -86,9 +86,13 @@ my @all_items = GetItemsInfo($biblionumber); my @hiddenitems; my $patron = Koha::Patrons->find( $borrowernumber ); our $borcat= q{}; +our $patron_branch = q{}; if ( C4::Context->preference('OpacHiddenItemsExceptions') ) { $borcat = $patron ? $patron->categorycode : q{}; } +if ( C4::Context->preference('OpacHiddenItemsLocalExceptions') ) { + $patron_branch = $patron ? $patron->branchcode : q{}; +} my $record = GetMarcBiblio({ biblionumber => $biblionumber, @@ -100,7 +104,7 @@ if ( ! $record ) { if ( scalar @all_items >= 1 ) { push @hiddenitems, - GetHiddenItemnumbers( { items => \@all_items, borcat => $borcat } ); + GetHiddenItemnumbers( { items => \@all_items, borcat => $borcat, patron_branch => $patron_branch } ); if (scalar @hiddenitems == scalar @all_items ) { print $query->redirect("/cgi-bin/koha/errors/404.pl"); # escape early @@ -242,7 +246,8 @@ if ($session->param('busc')) { my @newresults; my $search_context = { 'interface' => 'opac', - 'category' => $borcat + 'category' => $borcat, + 'patron_branch' => $patron_branch }; for (my $i=0;$i<@servers;$i++) { my $server = $servers[$i]; --- a/opac/opac-downloadcart.pl +++ a/opac/opac-downloadcart.pl @@ -49,11 +49,15 @@ my $dbh = C4::Context->dbh; if ($bib_list && $format) { + my $patron = Koha::Patrons->find( { borrowernumber => $borrowernumber } ); my $borcat = q{}; + my $patron_branch = q{}; if ( C4::Context->preference('OpacHiddenItemsExceptions') ) { # we need to fetch the borrower info here, so we can pass the category - my $borrower = Koha::Patrons->find( { borrowernumber => $borrowernumber } ); - $borcat = $borrower ? $borrower->categorycode : $borcat; + $borcat = $patron ? $patron->categorycode : $borcat; + } + if ( C4::Context->preference('OpacHiddenItemsLocalExceptions') ) { + $patron_branch = $patron ? $patron->branchcode : $patron_branch; } my @bibs = split( /\//, $bib_list ); @@ -76,10 +80,11 @@ if ($bib_list && $format) { foreach my $biblio (@bibs) { my $record = GetMarcBiblio({ - biblionumber => $biblio, - embed_items => 1, - opac => 1, - borcat => $borcat }); + biblionumber => $biblio, + embed_items => 1, + opac => 1, + borcat => $borcat, + patron_branch => $patron_branch }); my $framework = &GetFrameworkCode( $biblio ); $record_processor->options({ interface => 'opac', --- a/opac/opac-downloadshelf.pl +++ a/opac/opac-downloadshelf.pl @@ -50,11 +50,15 @@ my ( $template, $borrowernumber, $cookie ) = get_template_and_user ( } ); +my $patron = Koha::Patrons->find( { borrowernumber => $borrowernumber } ); my $borcat = q{}; +my $patron_branch = q{}; if ( C4::Context->preference('OpacHiddenItemsExceptions') ) { # we need to fetch the borrower info here, so we can pass the category - my $borrower = Koha::Patrons->find( { borrowernumber => $borrowernumber } ); - $borcat = $borrower ? $borrower->categorycode : $borcat; + $borcat = $patron ? $patron->categorycode : $borcat; +} +if ( C4::Context->preference('OpacHiddenItemsLocalExceptions') ) { + $patron_branch = $patron ? $patron->branchcode : $patron_branch; } my $shelfnumber = $query->param('shelfnumber'); --- a/opac/opac-export.pl +++ a/opac/opac-export.pl @@ -38,22 +38,28 @@ my $error = q{}; # Determine logged in user's patron category. # Blank if not logged in. my $userenv = C4::Context->userenv; +my $borrowernumber; +my $patron; my $borcat = q{}; +my $patron_branch = q{}; + if ($userenv) { - my $borrowernumber = $userenv->{'number'}; + $borrowernumber = $userenv->{'number'}; if ($borrowernumber) { - my $borrower = Koha::Patrons->find( { borrowernumber => $borrowernumber } ); - $borcat = $borrower ? $borrower->categorycode : $borcat; + $patron = Koha::Patrons->find( { borrowernumber => $borrowernumber } ); } } +$borcat = $patron ? $patron->categorycode : $borcat; +$patron_branch = $patron ? $patron->branchcode : $patron_branch; my $include_items = ($format =~ /bibtex/) ? 0 : 1; my $marc = $biblionumber ? GetMarcBiblio({ - biblionumber => $biblionumber, - embed_items => $include_items, - opac => 1, - borcat => $borcat }) + biblionumber => $biblionumber, + embed_items => $include_items, + opac => 1, + borcat => $borcat, + patron_branch => $patron_branch }) : undef; if(!$marc) { --- a/opac/opac-search.pl +++ a/opac/opac-search.pl @@ -632,6 +632,9 @@ $search_context->{'interface'} = 'opac'; if (C4::Context->preference('OpacHiddenItemsExceptions')){ $search_context->{'category'} = $patron ? $patron->categorycode : q{}; } +if (C4::Context->preference('OpacHiddenItemsLocalExceptions')){ + $search_context->{'patron_branch'} = $patron ? $patron->branchcode : q{}; +} for (my $i=0;$i<@servers;$i++) { my $server = $servers[$i]; --- a/opac/opac-sendbasket.pl +++ a/opac/opac-sendbasket.pl @@ -60,6 +60,7 @@ if ( $email_add ) { my $email = Koha::Email->new(); my $patron = Koha::Patrons->find( $borrowernumber ); my $borcat = $patron ? $patron->categorycode : q{}; + my $patron_branch = $patron ? $patron->branchcode : q{}; my $user_email = $patron->first_valid_email_address || C4::Context->preference('KohaAdminEmailAddress'); @@ -89,10 +90,11 @@ if ( $email_add ) { my $dat = GetBiblioData($biblionumber); next unless $dat; my $record = GetMarcBiblio({ - biblionumber => $biblionumber, - embed_items => 1, - opac => 1, - borcat => $borcat }); + biblionumber => $biblionumber, + embed_items => 1, + opac => 1, + borcat => $borcat, + patron_branch => $patron_branch }); my $marcauthorsarray = GetMarcAuthors( $record, $marcflavour ); my $marcsubjctsarray = GetMarcSubjects( $record, $marcflavour ); --- a/opac/opac-sendshelf.pl +++ a/opac/opac-sendshelf.pl @@ -81,6 +81,7 @@ if ( $email ) { my $patron = Koha::Patrons->find( $borrowernumber ); my $borcat = $patron ? $patron->categorycode : q{}; + my $patron_branch = $patron ? $patron->branchcode : q{}; my $shelf = Koha::Virtualshelves->find( $shelfid ); my $contents = $shelf->get_contents; @@ -91,10 +92,11 @@ if ( $email ) { while ( my $content = $contents->next ) { my $biblionumber = $content->biblionumber; my $record = GetMarcBiblio({ - biblionumber => $biblionumber, - embed_items => 1, - opac => 1, - borcat => $borcat }); + biblionumber => $biblionumber, + embed_items => 1, + opac => 1, + borcat => $borcat, + patron_branch => $patron_branch }); next unless $record; my $fw = GetFrameworkCode($biblionumber); my $dat = GetBiblioData($biblionumber); --- a/opac/opac-tags.pl +++ a/opac/opac-tags.pl @@ -228,10 +228,12 @@ if ($is_ajax) { my $results = []; my $my_tags = []; my $borcat = q{}; +my $patron_branch = q{}; if ($loggedinuser) { my $patron = Koha::Patrons->find( { borrowernumber => $loggedinuser } ); $borcat = $patron ? $patron->categorycode : $borcat; + $patron_branch = $patron ? $patron->branchcode : $patron_branch; my $should_hide = C4::Context->preference('OpacHiddenItems') // q{}; $should_hide = ( $should_hide =~ /\S/ ) ? 1 : 0; $my_tags = get_tag_rows({borrowernumber=>$loggedinuser}); @@ -240,10 +242,11 @@ if ($loggedinuser) { $tag->{visible} = 0; my $biblio = Koha::Biblios->find( $tag->{biblionumber} ); my $record = &GetMarcBiblio({ - biblionumber => $tag->{biblionumber}, - embed_items => 1, - opac => 1, - borcat => $borcat }); + biblionumber => $tag->{biblionumber}, + embed_items => 1, + opac => 1, + borcat => $borcat, + patron_branch => $patron_branch }); next unless $record; my $hidden_items = undef; my @hidden_itemnumbers; @@ -252,7 +255,8 @@ if ($loggedinuser) { @all_items = GetItemsInfo( $tag->{biblionumber} ); @hidden_itemnumbers = GetHiddenItemnumbers({ items => \@all_items, - borcat => $borcat }); + borcat => $borcat, + patron_branch => $patron_branch }); $hidden_items = \@hidden_itemnumbers; } next if ( $should_hide && scalar @all_items == scalar @hidden_itemnumbers ); @@ -310,10 +314,11 @@ if ($add_op) { 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 }); + biblionumber => $my_tag->{biblionumber}, + embed_items => 1, + opac => 1, + borcat => $borcat, + patron_branch => $patron_branch }); if ($check_biblio) { push @filtered_results, $my_tag; } --- a/opac/opac-user.pl +++ a/opac/opac-user.pl @@ -92,6 +92,7 @@ my $patron = Koha::Patrons->find( $borrowernumber ); my $borr = $patron->unblessed; # unblessed is a hash vs. object/undef. Hence the use of curly braces here. my $borcat = $borr ? $borr->{categorycode} : q{}; +my $patron_branch = $borr ? $borr->{branchcode} : q{}; my ( $today_year, $today_month, $today_day) = Today(); my ($warning_year, $warning_month, $warning_day) = split /-/, $borr->{'dateexpiry'}; @@ -213,10 +214,11 @@ if ( $pending_checkouts->count ) { # Useless test $issue->{rentalfines} = $rental_fines->total_outstanding; my $marcrecord = GetMarcBiblio({ - biblionumber => $issue->{'biblionumber'}, - embed_items => 1, - opac => 1, - borcat => $borcat }); + biblionumber => $issue->{'biblionumber'}, + embed_items => 1, + opac => 1, + borcat => $borcat, + patron_branch => $patron_branch }); $issue->{'subtitle'} = GetRecordValue('subtitle', $marcrecord, GetFrameworkCode($issue->{'biblionumber'})); # check if item is renewable my ($status,$renewerror) = CanBookBeRenewed( $borrowernumber, $issue->{'itemnumber'} ); --