From 01677f9048bc1b4d88e5cf7e039abea314505951 Mon Sep 17 00:00:00 2001 From: ahmed Date: Wed, 21 Jan 2015 14:33:47 -0500 Subject: [PATCH] Bug 10937 - Grouped ItemTypes - Patch should apply properly on latest master. This allows to group certain item types in a category, to be displayed (and searched) as such in OPAC's advanced search. For example, you can group Reserve 2h and Reserve 12h into a Reserve category. The 2 and 12h types won't appear anymore. This also allows to simply prevent an item type from displaying as a search option. TEST PLAN ------------------ 0) Back up database, so you can reset and retest easily. ;) 1) Apply the patch 2) Run Koha QA tool. 3) prove -v t/db_dependent/Koha.t -- all tests should pass. 4) run ./installer/data/mysql/updatedatabase.pl to add the two columns to itemtypes -- Does a meaningful message get printed? Are the columns added? "DESCRIBE itemtypes;" should list hideinopac and searchcategory. 5) You need to add a category to group your item types: a) In Intranet/Koha Admin/Authorized values, select DOCTYPECAT in the 'Show category:' dropdown i) If you do not have a DOCTYPECAT category, create one. b) Click button "New authorized value for DOCTYPECAT" c) Enter Authorized value: HARDWARE Description : Hardware Description (OPAC): Hardware 6) Group your items under that new category a) In Intranet/Koha Admin/Item types, choose (at least) two item types and for each: - Click action/Edit on the right column - Third row (below Description) is the Search category list box, select Hardware - click Save changes at the bottom 7) Select at least one item to be hidden in the OPAC search a) In Intranet/Koha Admin/Item types (again), choose a different item type: - Click action/Edit - Click the checkbox "Hide in OPAC" below the list of icons. 8) Go test your modifications a) Go to OPAC/Adv search. b) Validate that all items modified above (hidden or grouped) do not appear in Item type list c) Validate that new item type Hardware does appear instead. d) Select item Hardware, start Search. ) Validate returned items are the of the two types that were grouped into the Hardware category in step 4. Sponsored-by: Vanier college --- C4/Koha.pm | 59 +++++++++++++++++++- admin/authorised_values.pl | 2 +- admin/itemtypes.pl | 14 ++++- installer/data/mysql/kohastructure.sql | 2 + installer/data/mysql/updatedatabase.pl | 15 +++++ .../prog/en/modules/admin/itemtypes.tt | 32 +++++++++++ .../bootstrap/en/modules/opac-advsearch.tt | 20 ++++++- opac/opac-search.pl | 25 ++++++++- t/db_dependent/Koha.t | 46 ++++++++++++++- 9 files changed, 203 insertions(+), 12 deletions(-) diff --git a/C4/Koha.pm b/C4/Koha.pm index ec65be9..993b5db 100644 --- a/C4/Koha.pm +++ b/C4/Koha.pm @@ -29,9 +29,9 @@ use Koha::Cache; use Koha::DateUtils qw(dt_from_string); use DateTime::Format::MySQL; use Business::ISBN; -use autouse 'Data::Dumper' => qw(Dumper); +use autouse 'Data::cselectall_arrayref' => qw(Dumper); use DBI qw(:sql_types); - + use Data::Dumper; use vars qw($VERSION @ISA @EXPORT @EXPORT_OK $DEBUG); BEGIN { @@ -43,6 +43,7 @@ BEGIN { &subfield_is_koha_internal_p &GetPrinters &GetPrinter &GetItemTypes &getitemtypeinfo + &GetItemTypesCategorized &GetItemTypesByCategory &GetSupportName &GetSupportList &get_itemtypeinfos_of &getframeworks &getframeworkinfo @@ -273,6 +274,60 @@ sub GetItemTypes { } } +=head2 GetItemTypesCategorized + + $categories = GetItemTypesCategorized(); + +Returns a hashref containing search categories. +A search category will be put in the hash if at least one of its itemtypes is visible in OPAC. +The categories must be part of Authorized Values (DOCTYPECAT) + +=cut + +sub GetItemTypesCategorized { + my $dbh = C4::Context->dbh; + # Order is important, so that partially hidden (some items are not visible in OPAC) search + # categories will be visible. hideinopac=0 must be last. + my $query = q| + SELECT itemtype, description, imageurl, hideinopac, 0 as 'iscat' FROM itemtypes WHERE ISNULL(searchcategory) or length(searchcategory) = 0 + UNION + SELECT DISTINCT searchcategory AS `itemtype`, + authorised_values.lib_opac AS description, + authorised_values.imageurl AS imageurl, + hideinopac, 1 as 'iscat' + FROM itemtypes + LEFT JOIN authorised_values ON searchcategory = authorised_value + WHERE searchcategory > '' and hideinopac=1 + UNION + SELECT DISTINCT searchcategory AS `itemtype`, + authorised_values.lib_opac AS description, + authorised_values.imageurl AS imageurl, + hideinopac, 1 as 'iscat' + FROM itemtypes + LEFT JOIN authorised_values ON searchcategory = authorised_value + WHERE searchcategory > '' and hideinopac=0 + |; +return ($dbh->selectall_hashref($query,'itemtype')); +} + +=head2 GetItemTypesByCategory + + @results = GetItemTypesByCategory( $searchcategory ); + +Returns the itemtype code of all itemtypes included in a searchcategory. + +=cut + +sub GetItemTypesByCategory { + my ($category) = @_; + my $count = 0; + my @results; + my $dbh = C4::Context->dbh; + my $query = qq|SELECT itemtype FROM itemtypes WHERE searchcategory=?|; + my $tmp=$dbh->selectcol_arrayref($query,undef,$category); + return @$tmp; +} + sub get_itemtypeinfos_of { my @itemtypes = @_; diff --git a/admin/authorised_values.pl b/admin/authorised_values.pl index 453746c..d57935a 100755 --- a/admin/authorised_values.pl +++ b/admin/authorised_values.pl @@ -246,7 +246,7 @@ sub default_form { } # push koha system categories - foreach (qw(Asort1 Asort2 Bsort1 Bsort2 SUGGEST DAMAGED LOST REPORT_GROUP REPORT_SUBGROUP DEPARTMENT TERM SUGGEST_STATUS)) { + foreach (qw(Asort1 Asort2 Bsort1 Bsort2 SUGGEST DAMAGED LOST REPORT_GROUP REPORT_SUBGROUP DEPARTMENT TERM SUGGEST_STATUS DOCTYPECAT)) { push @category_list, $_ unless $categories{$_}; } diff --git a/admin/itemtypes.pl b/admin/itemtypes.pl index 1bfad90..f08dc33 100755 --- a/admin/itemtypes.pl +++ b/admin/itemtypes.pl @@ -112,6 +112,8 @@ if ( $op eq 'add_form' ) { $remote_image = $data->{imageurl}; } + my $searchcategory = GetAuthorisedValues("DOCTYPECAT", $data->{'searchcategory'}); + $template->param( itemtype => $itemtype, description => $data->{'description'}, @@ -125,6 +127,8 @@ if ( $op eq 'add_form' ) { imagesets => $imagesets, remote_image => $remote_image, sip_media_type => $data->{sip_media_type}, + hideinopac => $data->{'hideinopac'}, + searchcategory => $searchcategory, ); # END $OP eq ADD_FORM @@ -150,6 +154,8 @@ elsif ( $op eq 'add_validate' ) { , checkinmsg = ? , checkinmsgtype = ? , sip_media_type = ? + , hideinopac = ? + , searchcategory = ? WHERE itemtype = ? '; $sth = $dbh->prepare($query2); @@ -168,15 +174,17 @@ elsif ( $op eq 'add_validate' ) { $input->param('checkinmsg'), $input->param('checkinmsgtype'), $sip_media_type, + $input->param('hideinopac') ? 1 : 0, + $input->param('searchcategory'), $input->param('itemtype') ); } else { # add a new itemtype & not modif an old my $query = " INSERT INTO itemtypes - (itemtype,description,rentalcharge, notforloan, imageurl, summary, checkinmsg, checkinmsgtype, sip_media_type) + (itemtype,description,rentalcharge, notforloan, imageurl, summary, checkinmsg, checkinmsgtype, sip_media_type, hideinopac, searchcategory) VALUES - (?,?,?,?,?,?,?,?,?); + (?,?,?,?,?,?,?,?,?,?,?); "; my $sth = $dbh->prepare($query); my $image = $input->param('image'); @@ -192,6 +200,8 @@ elsif ( $op eq 'add_validate' ) { $input->param('checkinmsg'), $input->param('checkinmsgtype'), $sip_media_type, + $input->param('hideinopac') ? 1 : 0, + $input->param('searchcategory'), ); } diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql index 82868e7..25e31f6 100644 --- a/installer/data/mysql/kohastructure.sql +++ b/installer/data/mysql/kohastructure.sql @@ -1276,6 +1276,8 @@ CREATE TABLE `itemtypes` ( -- defines the item types checkinmsg VARCHAR(255), -- message that is displayed when an item with the given item type is checked in checkinmsgtype CHAR(16) DEFAULT 'message' NOT NULL, -- type (CSS class) for the checkinmsg, can be "alert" or "message" sip_media_type VARCHAR(3) DEFAULT NULL, -- SIP2 protocol media type for this itemtype + hideinopac tinyint(1) NOT NULL DEFAULT 0, -- Hide the item type from the search options in OPAC + searchcategory varchar(20) default NULL, -- Group this item type with others with the same value on OPAC search options PRIMARY KEY (`itemtype`), UNIQUE KEY `itemtype` (`itemtype`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl index 4653c02..0eceafd 100755 --- a/installer/data/mysql/updatedatabase.pl +++ b/installer/data/mysql/updatedatabase.pl @@ -9608,6 +9608,7 @@ if ( CheckVersion($DBversion) ) { SetVersion ($DBversion); } + $DBversion = "3.19.00.003"; if ( CheckVersion($DBversion) ) { my ($count) = $dbh->selectrow_array("SELECT COUNT(*) FROM borrowers GROUP BY userid HAVING COUNT(userid) > 1"); @@ -9669,6 +9670,20 @@ if ( CheckVersion($DBversion) ) { SetVersion ($DBversion); } +$DBversion = "3.19.00.XXX"; +if ( CheckVersion($DBversion) ) { + $dbh->do(q{ + ALTER TABLE itemtypes + ADD hideinopac TINYINT(1) NOT NULL DEFAULT 0 + AFTER sip_media_type, + ADD searchcategory VARCHAR(20) DEFAULT NULL + AFTER hideinopac; + }); + print "Upgrade to $DBversion done (Bug 10937 - Option to hide and group itemtypes from advanced search)\n"; + SetVersion($DBversion); +} + + =head1 FUNCTIONS =head2 TableExists($table) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/itemtypes.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/itemtypes.tt index 2e61a16..20fd49f 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/itemtypes.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/itemtypes.tt @@ -109,6 +109,25 @@ Item types administration [% END %]
  • Required
  • +
  • + Search category + + (Options are defined as the authorized values for the DOCTYPECAT category) +
  • + [% IF ( noItemTypeImages ) %]
  • Image: Item type images are disabled. To enable them, turn off the noItemTypeImages system preference
  • [% ELSE %] @@ -164,6 +183,15 @@ Item types administration [% END %]
    1. + + [% IF ( hideinopac ) %] + + [% ELSE %] + + [% END %] + (if checked, items of this type will be hidden as filters in OPAC's advanced search) +
    2. +
    3. [% IF ( notforloan ) %] [% ELSE %] @@ -260,7 +288,9 @@ Item types administration [% UNLESS ( noItemTypeImages ) %]Image[% END %] Code Description + Search category Not for loan + Hide in OPAC Charge Checkin message Actions @@ -274,7 +304,9 @@ Item types administration [% loo.description %] + [% loo.searchcategory %] [% IF ( loo.notforloan ) %]Yes[% ELSE %] [% END %] + [% IF ( loo.hideinopac ) %]Yes[% ELSE %] [% END %] [% UNLESS ( loo.notforloan ) %] [% loo.rentalcharge %] diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-advsearch.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-advsearch.tt index 12dd94f..c3568e2 100644 --- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-advsearch.tt +++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-advsearch.tt @@ -133,9 +133,25 @@ Limit to any of the following:
      [% FOREACH itemtypeloo IN advsearchloo.code_loop %] -
      + [% IF ((!itemtypeloo.searchcategory) AND (itemtypeloo.cat == 0)) OR (itemtypeloo.cat == 1) %] +
      + + +
      [% IF ( loop.last ) %]
      [% ELSE %][% UNLESS ( loop.count % 4 ) %]
      [% END %][% END %] + [% END %] [% END %]
      diff --git a/opac/opac-search.pl b/opac/opac-search.pl index b0feaeb..a560cba 100755 --- a/opac/opac-search.pl +++ b/opac/opac-search.pl @@ -84,7 +84,7 @@ my ($template,$borrowernumber,$cookie); my $template_name; my $template_type = 'basic'; my @params = $cgi->param("limit"); - +my @searchCategories = $cgi->param('searchcat'); my $format = $cgi->param("format") || ''; my $build_grouped_results = C4::Context->preference('OPACGroupResults'); @@ -194,7 +194,7 @@ my $languages_limit_loop = getLanguages($lang, 1); $template->param(search_languages_loop => $languages_limit_loop,); # load the Type stuff -my $itemtypes = GetItemTypes; +my $itemtypes = GetItemTypesCategorized; # the index parameter is different for item-level itemtypes my $itype_or_itemtype = (C4::Context->preference("item-level_itypes"))?'itype':'itemtype'; my @advancedsearchesloop; @@ -228,8 +228,13 @@ foreach my $advanced_srch_type (@advanced_search_types) { code => $thisitemtype, description => $itemtypes->{$thisitemtype}->{'description'}, imageurl=> getitemtypeimagelocation( 'opac', $itemtypes->{$thisitemtype}->{'imageurl'} ), + cat => $itemtypes->{$thisitemtype}->{'iscat'}, + hideinopac => $itemtypes->{$thisitemtype}->{'hideinopac'}, + searchcategory => $itemtypes->{$thisitemtype}->{'searchcategory'}, ); - push @itypesloop, \%row; + if ( !$itemtypes->{$thisitemtype}->{'hideinopac'} ) { + push @itypesloop, \%row; + } } my %search_code = ( advanced_search_type => $advanced_srch_type, code_loop => \@itypesloop ); @@ -247,6 +252,7 @@ foreach my $advanced_srch_type (@advanced_search_types) { ccl => $advanced_srch_type, code => $thisitemtype->{authorised_value}, description => $thisitemtype->{'lib_opac'} || $thisitemtype->{'lib'}, + searchcategory => $itemtypes->{$thisitemtype}->{'searchcategory'}, imageurl => getitemtypeimagelocation( 'opac', $thisitemtype->{'imageurl'} ), ); push @authvalueloop, \%row; @@ -426,6 +432,19 @@ my @nolimits = $cgi->param('nolimit'); my %is_nolimit = map { $_ => 1 } @nolimits; @limits = grep { not $is_nolimit{$_} } @limits; +if (@searchCategories > 0) { + my @tabcat; + foreach my $typecategory (@searchCategories) { + push (@tabcat, GetItemTypesByCategory($typecategory)); + } + + foreach my $itemtypeInCategory (@tabcat) { + push (@limits, "mc-$itype_or_itemtype,phr:".$itemtypeInCategory); + } +} + +@limits = map { uri_unescape($_) } @limits; + if($params->{'multibranchlimit'}) { my $multibranch = '('.join( " or ", map { "branch: $_ " } @{ GetBranchesInCategory( $params->{'multibranchlimit'} ) } ).')'; push @limits, $multibranch if ($multibranch ne '()'); diff --git a/t/db_dependent/Koha.t b/t/db_dependent/Koha.t index 2a6850a..84fc5eb 100644 --- a/t/db_dependent/Koha.t +++ b/t/db_dependent/Koha.t @@ -7,12 +7,13 @@ use strict; use warnings; use C4::Context; use Koha::DateUtils qw(dt_from_string); +use Data::Dumper; -use Test::More tests => 8; +use Test::More tests => 9; use DateTime::Format::MySQL; BEGIN { - use_ok('C4::Koha', qw( :DEFAULT GetDailyQuote )); + use_ok('C4::Koha', qw( :DEFAULT GetDailyQuote GetItemTypesByCategory GetItemTypesCategorized)); use_ok('C4::Members'); } @@ -312,4 +313,45 @@ subtest 'GetFrameworksLoop() tests' => sub { ); }; +subtest 'GetItemTypesByCategory GetItemTypesCategorized test' => sub{ + plan tests => 7; + + my $insertGroup = AddAuthorisedValue('DOCTYPECAT', 'Qwertyware'); + ok($insertGroup, "Create group Qwertyware"); + + my $query = "INSERT into itemtypes (itemtype, description, searchcategory, hideinopac) values (?,?,?,?)"; + my $insertSth = C4::Context->dbh->prepare($query); + $insertSth->execute('BKghjklo1', 'One type of book', '', 0); + $insertSth->execute('BKghjklo2', 'Another type of book', 'Qwertyware', 0); + $insertSth->execute('BKghjklo3', 'Yet another type of book', 'Qwertyware', 0); + + # Azertyware should not exist. + my @results = GetItemTypesByCategory('Azertyware'); + is(scalar @results, 0, 'GetItemTypesByCategory: Invalid category returns nothing'); + + @results = GetItemTypesByCategory('Qwertyware'); + my @expected = ( 'BKghjklo2', 'BKghjklo3' ); + is_deeply(\@results,\@expected,'GetItemTypesByCategory: valid category returns itemtypes'); + + # add more data since GetItemTypesCategorized's search is more subtle + $insertGroup = AddAuthorisedValue('DOCTYPECAT', 'Veryheavybook'); + $insertSth->execute('BKghjklo4', 'Another hidden book', 'Veryheavybook', 1); + + my $hrCat = GetItemTypesCategorized(); + ok(exists $hrCat->{Qwertyware}, 'GetItemTypesCategorized: fully visible category exists'); + ok($hrCat->{Veryheavybook} && + $hrCat->{Veryheavybook}->{hideinopac}==1, 'GetItemTypesCategorized: non-visible category hidden' ); + + $insertSth->execute('BKghjklo5', 'An hidden book', 'Qwertyware', 1); + $hrCat = GetItemTypesCategorized(); + ok(exists $hrCat->{Qwertyware}, 'GetItemTypesCategorized: partially visible category exists'); + + my @only = ( 'BKghjklo1', 'BKghjklo2', 'BKghjklo3', 'BKghjklo4', 'BKghjklo5', 'Qwertyware', 'Veryheavybook' ); + @results = (); + foreach my $key (@only) { + push @results, $key if exists $hrCat->{$key}; + } + @expected = ( 'BKghjklo1', 'Qwertyware', 'Veryheavybook' ); + is_deeply(\@results,\@expected, 'GetItemTypesCategorized: grouped and ungrouped items returned as expected.'); +}; $dbh->rollback(); -- 1.7.9.5