Bug 13562: Fix item search on item MARC subfields
authorJulian Maurice <julian.maurice@biblibre.com>
Wed, 14 Jan 2015 16:00:17 +0000 (17:00 +0100)
committerTomas Cohen Arazi <tomascohen@gmail.com>
Mon, 9 Feb 2015 13:28:09 +0000 (10:28 -0300)
Test plan:
1. Add 4 item search fields (in Administration › Items search fields):
   a. 1 biblio field linked to a DB field
   b. 1 biblio field not linked to a DB field
   c. 1 item field linked to a DB field
   d. 1 item field not linked to a DB field
2. Make sure you have some data in those fields to search on.
3. Go to item search page and do a search using these new fields, make
   sure the result is correct.

Signed-off-by: Nick <nick@quecheelibrary.org>
Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Tomas Cohen Arazi <tomascohen@gmail.com>
C4/Items.pm
t/db_dependent/Items.t

index 33143a5..a225b49 100644 (file)
@@ -2599,6 +2599,8 @@ sub SearchItemsByField {
 sub _SearchItems_build_where_fragment {
     my ($filter) = @_;
 
+    my $dbh = C4::Context->dbh;
+
     my $where_fragment;
     if (exists($filter->{conjunction})) {
         my (@where_strs, @where_args);
@@ -2635,13 +2637,33 @@ sub _SearchItems_build_where_fragment {
             if ($field =~ /^marc:(\d{3})(?:\$(\w))?$/) {
                 my $marcfield = $1;
                 my $marcsubfield = $2;
-                my $xpath;
-                if ($marcfield < 10) {
-                    $xpath = "//record/controlfield[\@tag=\"$marcfield\"]";
+                my ($kohafield) = $dbh->selectrow_array(q|
+                    SELECT kohafield FROM marc_subfield_structure
+                    WHERE tagfield=? AND tagsubfield=? AND frameworkcode=''
+                |, undef, $marcfield, $marcsubfield);
+
+                if ($kohafield) {
+                    $column = $kohafield;
                 } else {
-                    $xpath = "//record/datafield[\@tag=\"$marcfield\"]/subfield[\@code=\"$marcsubfield\"]";
+                    # MARC field is not linked to a DB field so we need to use
+                    # ExtractValue on biblioitems.marcxml or
+                    # items.more_subfields_xml, depending on the MARC field.
+                    my $xpath;
+                    my $sqlfield;
+                    my ($itemfield) = GetMarcFromKohaField('items.itemnumber');
+                    if ($marcfield eq $itemfield) {
+                        $sqlfield = 'more_subfields_xml';
+                        $xpath = '//record/datafield/subfield[@code="' . $marcsubfield . '"]';
+                    } else {
+                        $sqlfield = 'marcxml';
+                        if ($marcfield < 10) {
+                            $xpath = "//record/controlfield[\@tag=\"$marcfield\"]";
+                        } else {
+                            $xpath = "//record/datafield[\@tag=\"$marcfield\"]/subfield[\@code=\"$marcsubfield\"]";
+                        }
+                    }
+                    $column = "ExtractValue($sqlfield, '$xpath')";
                 }
-                $column = "ExtractValue(marcxml, '$xpath')";
             } else {
                 $column = $field;
             }
index d94b7b7..dfb1654 100755 (executable)
@@ -228,7 +228,7 @@ subtest q{Test Koha::Database->schema()->resultset('Item')->itemtype()} => sub {
 };
 
 subtest 'SearchItems test' => sub {
-    plan tests => 10;
+    plan tests => 13;
 
     # Start transaction
     $dbh->{AutoCommit} = 0;
@@ -337,6 +337,52 @@ subtest 'SearchItems test' => sub {
     }
     ok($found, "item1 found");
 
+    my ($itemfield) = GetMarcFromKohaField('items.itemnumber', '');
+
+    # Create item subfield 'z' without link
+    $dbh->do('DELETE FROM marc_subfield_structure WHERE tagfield=? AND tagsubfield="z" AND frameworkcode=""', undef, $itemfield);
+    $dbh->do('INSERT INTO marc_subfield_structure (tagfield, tagsubfield, frameworkcode) VALUES (?, "z", "")', undef, $itemfield);
+
+    # Clear cache
+    $C4::Context::context->{marcfromkohafield} = undef;
+    $C4::Biblio::inverted_field_map = undef;
+
+    my $item3_record = new MARC::Record;
+    $item3_record->append_fields(
+        new MARC::Field($itemfield, '', '', 'z' => 'foobar')
+    );
+    my (undef, undef, $item3_itemnumber) = AddItemFromMarc($item3_record,
+        $biblionumber);
+
+    # Search item where item subfield z is "foobar"
+    $filter = {
+        field => 'marc:' . $itemfield . '$z',
+        query => 'foobar',
+        operator => 'like',
+    };
+    ($items, $total_results) = SearchItems($filter);
+    ok(scalar @$items == 1, 'found 1 item with $z = "foobar"');
+
+    # Link $z to items.itemnotes (and make sure there is no other subfields
+    # linked to it)
+    $dbh->do('DELETE FROM marc_subfield_structure WHERE kohafield="items.itemnotes" AND frameworkcode=""', undef, $itemfield);
+    $dbh->do('UPDATE marc_subfield_structure SET kohafield="items.itemnotes" WHERE tagfield=? AND tagsubfield="z" AND frameworkcode=""', undef, $itemfield);
+
+    # Clear cache
+    $C4::Context::context->{marcfromkohafield} = undef;
+    $C4::Biblio::inverted_field_map = undef;
+
+    ModItemFromMarc($item3_record, $biblionumber, $item3_itemnumber);
+
+    # Make sure the link is used
+    my $item3 = GetItem($item3_itemnumber);
+    ok($item3->{itemnotes} eq 'foobar', 'itemnotes eq "foobar"');
+
+    # Do the same search again.
+    # This time it will search in items.itemnotes
+    ($items, $total_results) = SearchItems($filter);
+    ok(scalar @$items == 1, 'found 1 item with itemnotes = "foobar"');
+
     $dbh->rollback;
 };