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

(-)a/C4/XSLT.pm (-3 / +2 lines)
Lines 29-35 use C4::Koha qw( xml_escape ); Link Here
29
use C4::Biblio qw( GetAuthorisedValueDesc GetFrameworkCode GetMarcStructure );
29
use C4::Biblio qw( GetAuthorisedValueDesc GetFrameworkCode GetMarcStructure );
30
use Koha::AuthorisedValues;
30
use Koha::AuthorisedValues;
31
use Koha::ItemTypes;
31
use Koha::ItemTypes;
32
use Koha::Util::Search;
33
use Koha::XSLT::Base;
32
use Koha::XSLT::Base;
34
use Koha::Libraries;
33
use Koha::Libraries;
35
34
Lines 286-292 sub XSLTParse4Display { Link Here
286
    # possibly insert component records into Detail views
285
    # possibly insert component records into Detail views
287
    if ($xslsyspref =~ m/Details/) {
286
    if ($xslsyspref =~ m/Details/) {
288
        my $biblio = Koha::Biblios->find( $biblionumber );
287
        my $biblio = Koha::Biblios->find( $biblionumber );
289
        my $components = $biblio->get_marc_components(300);
288
        my $components = $biblio->get_marc_analytics(300);
290
        $variables->{show_analytics_link} = ( scalar @{$components} == 0 ) ? 0 : 1;
289
        $variables->{show_analytics_link} = ( scalar @{$components} == 0 ) ? 0 : 1;
291
290
292
        my $showcomp = C4::Context->preference('ShowComponentRecords');
291
        my $showcomp = C4::Context->preference('ShowComponentRecords');
Lines 300-306 sub XSLTParse4Display { Link Here
300
299
301
             $variables->{show_analytics_link} = 0;
300
             $variables->{show_analytics_link} = 0;
302
301
303
             my $search_query = Koha::Util::Search::get_component_part_query($biblionumber);
302
             my $search_query = $biblio->get_analytics_query;
304
             $variables->{ComponentPartQuery} = $search_query;
303
             $variables->{ComponentPartQuery} = $search_query;
305
304
306
             my @componentPartRecordXML = ('<componentPartRecords>');
305
             my @componentPartRecordXML = ('<componentPartRecords>');
(-)a/Koha/Biblio.pm (-6 / +48 lines)
Lines 43-49 use Koha::Suggestions; Link Here
43
use Koha::Subscriptions;
43
use Koha::Subscriptions;
44
use Koha::SearchEngine;
44
use Koha::SearchEngine;
45
use Koha::SearchEngine::Search;
45
use Koha::SearchEngine::Search;
46
use Koha::Util::Search;
47
46
48
=head1 NAME
47
=head1 NAME
49
48
Lines 479-499 sub suggestions { Link Here
479
    return Koha::Suggestions->_new_from_dbic( $suggestions_rs );
478
    return Koha::Suggestions->_new_from_dbic( $suggestions_rs );
480
}
479
}
481
480
482
=head3 get_marc_components
481
=head3 get_marc_analytics
483
482
484
  my $components = $self->get_marc_components();
483
  my $analytics = $self->get_marc_analytics();
485
484
486
Returns an array of MARCXML data, which are component parts of
485
Returns an array of MARCXML data, which are analytic parts of
487
this object (MARC21 773$w points to this)
486
this object (MARC21 773$w points to this)
488
487
489
=cut
488
=cut
490
489
491
sub get_marc_components {
490
sub get_marc_analytics {
492
    my ($self, $max_results) = @_;
491
    my ($self, $max_results) = @_;
493
492
494
    return [] if (C4::Context->preference('marcflavour') ne 'MARC21');
493
    return [] if (C4::Context->preference('marcflavour') ne 'MARC21');
495
494
496
    my $searchstr = Koha::Util::Search::get_component_part_query($self->id);
495
    my $searchstr = $self->get_analytics_query;
497
496
498
    if (defined($searchstr)) {
497
    if (defined($searchstr)) {
499
        my $searcher = Koha::SearchEngine::Search->new({index => $Koha::SearchEngine::BIBLIOS_INDEX});
498
        my $searcher = Koha::SearchEngine::Search->new({index => $Koha::SearchEngine::BIBLIOS_INDEX});
Lines 504-509 sub get_marc_components { Link Here
504
    return $self->{_components} || [];
503
    return $self->{_components} || [];
505
}
504
}
506
505
506
=head2 get_analytics_query
507
508
Returns a query which can be used to search for all component parts of MARC21 biblios
509
510
=cut
511
512
sub get_analytics_query {
513
    my ($self) = @_;
514
515
    my $marc = $self->metadata->record;
516
517
    my $searchstr;
518
    if ( C4::Context->preference('UseControlNumber') ) {
519
        my $pf001 = $marc->field('001') || undef;
520
521
        if ( defined($pf001) ) {
522
            my $pf003 = $marc->field('003') || undef;
523
524
            if ( !defined($pf003) ) {
525
                # search for 773$w='Host001'
526
                $searchstr = "rcn:" . $pf001->data();
527
            }
528
            else {
529
                $searchstr  = "(";
530
                # search for (773$w='Host001' and 003='Host003') or 773$w='Host003 Host001')
531
                $searchstr .= "(rcn:" . $pf001->data() . " AND cni:" . $pf003->data() . ")";
532
                $searchstr .= " OR rcn:" . $pf003->data() . " " . $pf001->data();
533
                $searchstr .= ")";
534
            }
535
536
            # limit to monograph and serial component part records
537
            $searchstr .= " AND (bib-level:a OR bib-level:b)";
538
        }
539
    }
540
    else {
541
        my $cleaned_title = $marc->title;
542
        $cleaned_title =~ tr|/||;
543
        $searchstr = "Host-item:($cleaned_title)";
544
    }
545
546
    return $searchstr;
547
}
548
507
=head3 subscriptions
549
=head3 subscriptions
508
550
509
my $subscriptions = $self->subscriptions
551
my $subscriptions = $self->subscriptions
(-)a/Koha/Util/Search.pm (-73 lines)
Lines 1-73 Link Here
1
package Koha::Util::Search;
2
3
# Copyright 2020 University of Helsinki
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use C4::Biblio qw( GetMarcBiblio );
23
24
=head1 NAME
25
26
Koha::Util::Search - functions to build complex search queries
27
28
=head1 FUNCTIONS
29
30
=head2 get_component_part_query
31
32
Returns a query which can be used to search for all component parts of MARC21 biblios
33
34
=cut
35
36
sub get_component_part_query {
37
    my ($biblionumber) = @_;
38
39
    my $marc = GetMarcBiblio( { biblionumber => $biblionumber } );
40
41
    my $searchstr;
42
    if ( C4::Context->preference('UseControlNumber') ) {
43
        my $pf001 = $marc->field('001') || undef;
44
45
        if ( defined($pf001) ) {
46
            my $pf003 = $marc->field('003') || undef;
47
48
            if ( !defined($pf003) ) {
49
                # search for 773$w='Host001'
50
                $searchstr = "rcn:" . $pf001->data();
51
            }
52
            else {
53
                $searchstr  = "(";
54
                # search for (773$w='Host001' and 003='Host003') or 773$w='Host003 Host001')
55
                $searchstr .= "(rcn:" . $pf001->data() . " AND cni:" . $pf003->data() . ")";
56
                $searchstr .= " OR rcn:" . $pf003->data() . " " . $pf001->data();
57
                $searchstr .= ")";
58
            }
59
60
            # limit to monograph and serial component part records
61
            $searchstr .= " AND (bib-level:a OR bib-level:b)";
62
        }
63
    }
64
    else {
65
        my $cleaned_title = $marc->title;
66
        $cleaned_title =~ tr|/||;
67
        $searchstr = "Host-item:($cleaned_title)";
68
    }
69
70
    return $searchstr;
71
}
72
73
1;
(-)a/t/Koha/Util/Search.t (-54 lines)
Lines 1-54 Link Here
1
#!/usr/bin/perl
2
#
3
# Copyright 2020 University of Helsinki
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use Test::More tests => 1;
23
24
use t::lib::Mocks;
25
use t::lib::TestBuilder;
26
27
use C4::Biblio qw( GetMarcBiblio ModBiblioMarc );
28
use Koha::Util::Search;
29
use MARC::Field;
30
31
my $builder = t::lib::TestBuilder->new;
32
33
subtest 'get_component_part_query' => sub {
34
    plan tests => 3;
35
36
    my $biblio = $builder->build_sample_biblio();
37
    my $biblionumber = $biblio->biblionumber;
38
    my $record = GetMarcBiblio({ biblionumber => $biblionumber });
39
40
    t::lib::Mocks::mock_preference( 'UseControlNumber', '0' );
41
    is(Koha::Util::Search::get_component_part_query($biblionumber), "Host-item:(Some boring read)", "UseControlNumber disabled");
42
43
    t::lib::Mocks::mock_preference( 'UseControlNumber', '1' );
44
    my $marc_001_field = MARC::Field->new('001', $biblionumber);
45
    $record->append_fields($marc_001_field);
46
    ModBiblioMarc($record, $biblionumber);
47
48
    is(Koha::Util::Search::get_component_part_query($biblionumber), "rcn:$biblionumber AND (bib-level:a OR bib-level:b)", "UseControlNumber enabled without MarcOrgCode");
49
50
    my $marc_003_field = MARC::Field->new('003', 'OSt');
51
    $record->append_fields($marc_003_field);
52
    ModBiblioMarc($record, $biblionumber);
53
    is(Koha::Util::Search::get_component_part_query($biblionumber), "((rcn:$biblionumber AND cni:OSt) OR rcn:OSt $biblionumber) AND (bib-level:a OR bib-level:b)", "UseControlNumber enabled with MarcOrgCode");
54
};
(-)a/t/db_dependent/Koha/Biblio.t (-9 / +34 lines)
Lines 17-25 Link Here
17
17
18
use Modern::Perl;
18
use Modern::Perl;
19
19
20
use Test::More tests => 17;
20
use Test::More tests => 18;
21
21
22
use C4::Biblio qw( AddBiblio ModBiblio );
22
use C4::Biblio qw( AddBiblio ModBiblio ModBiblioMarc );
23
use Koha::Database;
23
use Koha::Database;
24
use Koha::Caches;
24
use Koha::Caches;
25
use Koha::Acquisition::Orders;
25
use Koha::Acquisition::Orders;
Lines 507-513 subtest 'suggestions() tests' => sub { Link Here
507
    $schema->storage->txn_rollback;
507
    $schema->storage->txn_rollback;
508
};
508
};
509
509
510
subtest 'get_marc_components() tests' => sub {
510
subtest 'get_marc_analytics() tests' => sub {
511
511
512
    plan tests => 3;
512
    plan tests => 3;
513
513
Lines 519-531 subtest 'get_marc_components() tests' => sub { Link Here
519
    my $search_mod = Test::MockModule->new( 'Koha::SearchEngine::Zebra::Search' );
519
    my $search_mod = Test::MockModule->new( 'Koha::SearchEngine::Zebra::Search' );
520
    $search_mod->mock( 'simple_search_compat', \&search_component_record2 );
520
    $search_mod->mock( 'simple_search_compat', \&search_component_record2 );
521
521
522
    my @components = $host_biblio->get_marc_components;
522
    my @components = $host_biblio->get_marc_analytics;
523
    is( ref(\@components), 'ARRAY', 'Return type is correct' );
523
    is( ref(\@components), 'ARRAY', 'Return type is correct' );
524
524
525
    is_deeply(
525
    is_deeply(
526
        [@components],
526
        [@components],
527
        [()],
527
        [[]],
528
        '->get_marc_components returns an empty ARRAY'
528
        '->get_marc_analytics returns an empty ARRAY'
529
    );
529
    );
530
530
531
    $search_mod->unmock( 'simple_search_compat');
531
    $search_mod->unmock( 'simple_search_compat');
Lines 533-547 subtest 'get_marc_components() tests' => sub { Link Here
533
    my $component_record = component_record1()->as_xml();
533
    my $component_record = component_record1()->as_xml();
534
534
535
    is_deeply(
535
    is_deeply(
536
        $host_biblio->get_marc_components,
536
        $host_biblio->get_marc_analytics,
537
        [($component_record)],
537
        [($component_record)],
538
        '->get_marc_components returns the related component part record'
538
        '->get_marc_analytics returns the related component part record'
539
    );
539
    );
540
    $search_mod->unmock( 'simple_search_compat');
540
    $search_mod->unmock( 'simple_search_compat');
541
541
542
    $schema->storage->txn_rollback;
542
    $schema->storage->txn_rollback;
543
};
543
};
544
544
545
subtest 'get_analytics_query' => sub {
546
    plan tests => 3;
547
548
    my $biblio = $builder->build_sample_biblio();
549
    my $biblionumber = $biblio->biblionumber;
550
    my $record = $biblio->metadata->record;
551
552
    t::lib::Mocks::mock_preference( 'UseControlNumber', '0' );
553
    is($biblio->get_analytics_query, "Host-item:(Some boring read)", "UseControlNumber disabled");
554
555
    t::lib::Mocks::mock_preference( 'UseControlNumber', '1' );
556
    my $marc_001_field = MARC::Field->new('001', $biblionumber);
557
    $record->append_fields($marc_001_field);
558
    C4::Biblio::ModBiblio( $record, $biblio->biblionumber );
559
    $biblio = Koha::Biblios->find( $biblio->biblionumber);
560
561
    is($biblio->get_analytics_query, "rcn:$biblionumber AND (bib-level:a OR bib-level:b)", "UseControlNumber enabled without MarcOrgCode");
562
563
    my $marc_003_field = MARC::Field->new('003', 'OSt');
564
    $record->append_fields($marc_003_field);
565
    C4::Biblio::ModBiblio( $record, $biblio->biblionumber );
566
    $biblio = Koha::Biblios->find( $biblio->biblionumber);
567
568
    is($biblio->get_analytics_query, "((rcn:$biblionumber AND cni:OSt) OR rcn:OSt $biblionumber) AND (bib-level:a OR bib-level:b)", "UseControlNumber enabled with MarcOrgCode");
569
};
570
545
subtest 'orders() and active_orders() tests' => sub {
571
subtest 'orders() and active_orders() tests' => sub {
546
572
547
    plan tests => 5;
573
    plan tests => 5;
548
- 

Return to bug 11175