View | Details | Raw Unified | Return to bug 8211
Collapse All | Expand All

(-)a/C4/Search.pm (+102 lines)
Lines 34-39 use C4::Charset; Link Here
34
use YAML;
34
use YAML;
35
use URI::Escape;
35
use URI::Escape;
36
use Business::ISBN;
36
use Business::ISBN;
37
use MARC::Record;
38
use MARC::Field;
37
39
38
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $DEBUG);
40
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $DEBUG);
39
41
Lines 1028-1033 sub getIndexes{ Link Here
1028
    return \@indexes;
1030
    return \@indexes;
1029
}
1031
}
1030
1032
1033
=head2 _handle_exploding_index
1034
1035
    my $query = _handle_exploding_index($index, $term)
1036
1037
Callback routine to generate the search for "exploding" indexes (i.e.
1038
those indexes which are turned into multiple or-connected searches based
1039
on authority data).
1040
1041
=cut
1042
1043
sub _handle_exploding_index {
1044
    my ( $index, $term ) = @_;
1045
1046
    return unless ($index =~ m/(su-br|su-na|su-rl)/ && $term);
1047
1048
    my $marcflavour = C4::Context->preference('marcflavour');
1049
1050
    my $codesubfield = $marcflavour eq 'UNIMARC' ? '5' : 'w';
1051
    my $wantedcodes = '';
1052
    my @subqueries = ( "(su=\"$term\")");
1053
    my ($error, $results, $total_hits) = SimpleSearch( "Heading,wrdl=$term", undef, undef, [ "authorityserver" ] );
1054
    foreach my $auth (@$results) {
1055
        my $record = MARC::Record->new_from_usmarc($auth);
1056
        my @references = $record->field('5..');
1057
        if (@references) {
1058
            if ($index eq 'su-br') {
1059
                $wantedcodes = 'g';
1060
            } elsif ($index eq 'su-na') {
1061
                $wantedcodes = 'h';
1062
            } elsif ($index eq 'su-rl') {
1063
                $wantedcodes = '';
1064
            }
1065
            foreach my $reference (@references) {
1066
                my $codes = $reference->subfield($codesubfield);
1067
                push @subqueries, '(su="' . $reference->as_string('abcdefghijlmnopqrstuvxyz') . '")' if (($codes && $codes eq $wantedcodes) || !$wantedcodes);
1068
            }
1069
        }
1070
    }
1071
    return join(' or ', @subqueries);
1072
}
1073
1074
=head2 parseQuery
1075
1076
    ( $operators, $operands, $indexes, $limits,
1077
      $sort_by, $scan, $lang ) =
1078
            buildQuery ( $operators, $operands, $indexes, $limits, $sort_by, $scan, $lang);
1079
1080
Shim function to ease the transition from buildQuery to a new QueryParser.
1081
This function is called at the beginning of buildQuery, and modifies
1082
buildQuery's input. If it can handle the input, it returns a query that
1083
buildQuery will not try to parse.
1084
=cut
1085
1086
sub parseQuery {
1087
    my ( $operators, $operands, $indexes, $limits, $sort_by, $scan, $lang) = @_;
1088
1089
    my @operators = $operators ? @$operators : ();
1090
    my @indexes   = $indexes   ? @$indexes   : ();
1091
    my @operands  = $operands  ? @$operands  : ();
1092
    my @limits    = $limits    ? @$limits    : ();
1093
    my @sort_by   = $sort_by   ? @$sort_by   : ();
1094
1095
    my $query = $operands[0];
1096
    my $index;
1097
    my $term;
1098
1099
# TODO: once we are using QueryParser, all this special case code for
1100
#       exploded search indexes will be replaced by a callback to
1101
#       _handle_exploding_index
1102
    if ( $query =~ m/^(.*)\b(su-br|su-na|su-rl)[:=](\w.*)$/ ) {
1103
        $query = $1;
1104
        $index = $2;
1105
        $term  = $3;
1106
    } else {
1107
        $query = '';
1108
        for ( my $i = 0 ; $i <= @operands ; $i++ ) {
1109
            if ($operands[$i] && $indexes[$i] =~ m/(su-br|su-na|su-rl)/) {
1110
                $index = $indexes[$i];
1111
                $term = $operands[$i];
1112
            } elsif ($operands[$i]) {
1113
                $query .= $operators[$i] eq 'or' ? ' or ' : ' and ' if ($query);
1114
                $query .= "($indexes[$i]:$operands[$i])";
1115
            }
1116
        }
1117
    }
1118
1119
    if ($index) {
1120
        my $queryPart = _handle_exploding_index($index, $term);
1121
        if ($queryPart) {
1122
            $query .= "($queryPart)";
1123
        }
1124
        $operators = ();
1125
        $operands[0] = "ccl=$query";
1126
    }
1127
1128
    return ( $operators, \@operands, $indexes, $limits, $sort_by, $scan, $lang);
1129
}
1130
1031
=head2 buildQuery
1131
=head2 buildQuery
1032
1132
1033
( $error, $query,
1133
( $error, $query,
Lines 1049-1054 sub buildQuery { Link Here
1049
1149
1050
    warn "---------\nEnter buildQuery\n---------" if $DEBUG;
1150
    warn "---------\nEnter buildQuery\n---------" if $DEBUG;
1051
1151
1152
    ( $operators, $operands, $indexes, $limits, $sort_by, $scan, $lang) = parseQuery($operators, $operands, $indexes, $limits, $sort_by, $scan, $lang);
1153
1052
    # dereference
1154
    # dereference
1053
    my @operators = $operators ? @$operators : ();
1155
    my @operators = $operators ? @$operators : ();
1054
    my @indexes   = $indexes   ? @$indexes   : ();
1156
    my @indexes   = $indexes   ? @$indexes   : ();
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/search_indexes.inc (+5 lines)
Lines 13-18 Link Here
13
    <option value="se">&nbsp;&nbsp;&nbsp;&nbsp; Series title</option>
13
    <option value="se">&nbsp;&nbsp;&nbsp;&nbsp; Series title</option>
14
    <option value="su">Subject</option>
14
    <option value="su">Subject</option>
15
    <option value="su,phr">&nbsp;&nbsp;&nbsp;&nbsp; Subject as phrase</option>
15
    <option value="su,phr">&nbsp;&nbsp;&nbsp;&nbsp; Subject as phrase</option>
16
    [% IF ( expanded_options ) %]
17
        <option value="su-br">&nbsp;&nbsp;&nbsp;&nbsp; Subject and broader terms</option>
18
        <option value="su-na">&nbsp;&nbsp;&nbsp;&nbsp; Subject and narrower terms</option>
19
        <option value="su-rl">&nbsp;&nbsp;&nbsp;&nbsp; Subject and related terms</option>
20
    [% END %]
16
    <option value="bc">Barcode</option>
21
    <option value="bc">Barcode</option>
17
    <option value="location">Shelving location</option>
22
    <option value="location">Shelving location</option>
18
    <option value="sn">Standard number</option>
23
    <option value="sn">Standard number</option>
(-)a/koha-tmpl/opac-tmpl/prog/en/modules/opac-advsearch.tt (-1 / +4 lines)
Lines 67-74 Link Here
67
        <select name="idx">
67
        <select name="idx">
68
            <option value="kw">Keyword</option>
68
            <option value="kw">Keyword</option>
69
            <option value="su,wrdl">Subject</option>
69
            <option value="su,wrdl">Subject</option>
70
[% IF ( search_boxes_loo.expanded_options ) %]
70
[% IF ( expanded_options ) %]
71
            <option value="su,phr">&nbsp;&nbsp;&nbsp;&nbsp; Subject phrase</option>
71
            <option value="su,phr">&nbsp;&nbsp;&nbsp;&nbsp; Subject phrase</option>
72
            <option value="su-br">&nbsp;&nbsp;&nbsp;&nbsp; Subject and broader terms</option>
73
            <option value="su-na">&nbsp;&nbsp;&nbsp;&nbsp; Subject and narrower terms</option>
74
            <option value="su-rl">&nbsp;&nbsp;&nbsp;&nbsp; Subject and related terms</option>
72
[% END %]
75
[% END %]
73
            <option value="ti">Title</option>
76
            <option value="ti">Title</option>
74
[% IF ( expanded_options ) %]
77
[% IF ( expanded_options ) %]
(-)a/t/db_dependent/Search.t (-2 / +79 lines)
Lines 12-18 use YAML; Link Here
12
use C4::Debug;
12
use C4::Debug;
13
require C4::Context;
13
require C4::Context;
14
14
15
use Test::More tests => 57;
15
use Test::More tests => 78;
16
use Test::MockModule;
16
use Test::MockModule;
17
use MARC::Record;
17
use MARC::Record;
18
use File::Spec;
18
use File::Spec;
Lines 515-518 END { Link Here
515
    }
515
    }
516
}
516
}
517
517
518
# Testing exploding indexes
519
my $term;
520
my $searchmodule = new Test::MockModule('C4::Search');
521
$searchmodule->mock('SimpleSearch', sub {
522
    my $query = shift;
523
524
    is($query, "Heading,wrdl=$term", "Searching for expected term '$term' for exploding") or return '', [], 0;
525
526
    my $record = MARC::Record->new;
527
    if ($query =~ m/Arizona/) {
528
        $record->add_fields(
529
            [ '001', '1234' ],
530
            [ '151', ' ', ' ', a => 'Arizona' ],
531
            [ '551', ' ', ' ', a => 'United States', w => 'g' ],
532
            [ '551', ' ', ' ', a => 'Maricopa County', w => 'h' ],
533
            [ '551', ' ', ' ', a => 'Navajo County', w => 'h' ],
534
            [ '551', ' ', ' ', a => 'Pima County', w => 'h' ],
535
            [ '551', ' ', ' ', a => 'New Mexico' ],
536
            );
537
    }
538
    return '', [ $record->as_usmarc() ], 1;
539
});
540
541
$term = 'Arizona';
542
( $error, $query, $simple_query, $query_cgi,
543
$query_desc, $limit, $limit_cgi, $limit_desc,
544
$stopwords_removed, $query_type ) = buildQuery([], [ $term ], [ 'su-br' ], [  ], [], 0, 'en');
545
matchesExplodedTerms("Advanced search for broader subjects", $query, 'Arizona', 'United States');
546
547
( $error, $query, $simple_query, $query_cgi,
548
$query_desc, $limit, $limit_cgi, $limit_desc,
549
$stopwords_removed, $query_type ) = buildQuery([], [ $term ], [ 'su-na' ], [  ], [], 0, 'en');
550
matchesExplodedTerms("Advanced search for narrower subjects", $query, 'Arizona', 'Maricopa County', 'Navajo County', 'Pima County');
551
552
( $error, $query, $simple_query, $query_cgi,
553
$query_desc, $limit, $limit_cgi, $limit_desc,
554
$stopwords_removed, $query_type ) = buildQuery([], [ $term ], [ 'su-rl' ], [  ], [], 0, 'en');
555
matchesExplodedTerms("Advanced search for related subjects", $query, 'Arizona', 'United States', 'Maricopa County', 'Navajo County', 'Pima County');
556
557
( $error, $query, $simple_query, $query_cgi,
558
$query_desc, $limit, $limit_cgi, $limit_desc,
559
$stopwords_removed, $query_type ) = buildQuery([], [ "$term", 'history' ], [ 'su-rl', 'kw' ], [  ], [], 0, 'en');
560
matchesExplodedTerms("Advanced search for related subjects and keyword 'history' searches related subjects", $query, 'Arizona', 'United States', 'Maricopa County', 'Navajo County', 'Pima County');
561
like($query, qr/history/, "Advanced search for related subjects and keyword 'history' searches for 'history'");
562
563
( $error, $query, $simple_query, $query_cgi,
564
$query_desc, $limit, $limit_cgi, $limit_desc,
565
$stopwords_removed, $query_type ) = buildQuery([], [ 'history', "$term" ], [ 'kw', 'su-rl' ], [  ], [], 0, 'en');
566
matchesExplodedTerms("Order of terms doesn't matter for advanced search", $query, 'Arizona', 'United States', 'Maricopa County', 'Navajo County', 'Pima County');
567
like($query, qr/history/, "Order of terms doesn't matter for advanced search");
568
569
( $error, $query, $simple_query, $query_cgi,
570
$query_desc, $limit, $limit_cgi, $limit_desc,
571
$stopwords_removed, $query_type ) = buildQuery([], [ "su-br:$term" ], [  ], [  ], [], 0, 'en');
572
matchesExplodedTerms("Simple search for broader subjects", $query, 'Arizona', 'United States');
573
574
( $error, $query, $simple_query, $query_cgi,
575
$query_desc, $limit, $limit_cgi, $limit_desc,
576
$stopwords_removed, $query_type ) = buildQuery([], [ "su-na:$term" ], [  ], [  ], [], 0, 'en');
577
matchesExplodedTerms("Simple search for narrower subjects", $query, 'Arizona', 'Maricopa County', 'Navajo County', 'Pima County');
578
579
( $error, $query, $simple_query, $query_cgi,
580
$query_desc, $limit, $limit_cgi, $limit_desc,
581
$stopwords_removed, $query_type ) = buildQuery([], [ "su-rl:$term" ], [  ], [  ], [], 0, 'en');
582
matchesExplodedTerms("Simple search for related subjects", $query, 'Arizona', 'United States', 'Maricopa County', 'Navajo County', 'Pima County');
583
584
( $error, $query, $simple_query, $query_cgi,
585
$query_desc, $limit, $limit_cgi, $limit_desc,
586
$stopwords_removed, $query_type ) = buildQuery([], [ "history and su-rl:$term" ], [  ], [  ], [], 0, 'en');
587
matchesExplodedTerms("Simple search for related subjects and keyword 'history' searches related subjects", $query, 'Arizona', 'United States', 'Maricopa County', 'Navajo County', 'Pima County');
588
like($query, qr/history/, "Simple search for related subjects and keyword 'history' searches for 'history'");
589
590
sub matchesExplodedTerms {
591
    my ($message, $query, @terms) = @_;
592
    my $match = "(( or )?\\((" . join ('|', map { "su=\"$_\"" } @terms) . ")\\)){" . scalar(@terms) . "}";
593
    like($query, qr/$match/, $message);
594
}
595
518
1;
596
1;
519
- 

Return to bug 8211