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

(-)a/Koha/SearchEngine/Elasticsearch/Search.pm (-2 / +38 lines)
Lines 54-59 use MARC::File::XML; Link Here
54
use MIME::Base64 qw( decode_base64 );
54
use MIME::Base64 qw( decode_base64 );
55
use JSON;
55
use JSON;
56
56
57
use POSIX qw(setlocale LC_COLLATE);
58
use Unicode::Collate::Locale;
59
57
Koha::SearchEngine::Elasticsearch::Search->mk_accessors(qw( store ));
60
Koha::SearchEngine::Elasticsearch::Search->mk_accessors(qw( store ));
58
61
59
=head2 search
62
=head2 search
Lines 427-432 sub max_result_window { Link Here
427
    return $max_result_window;
430
    return $max_result_window;
428
}
431
}
429
432
433
434
=head2 _sort_facets
435
436
    my $facets = _sort_facets($facets);
437
438
Sorts facets using a locale.
439
440
=cut
441
442
sub _sort_facets {
443
    my ( $self, $args ) = @_;
444
    my $facets = $args->{facets};
445
    my $locale = $args->{locale};
446
    if ( !$locale ) {
447
448
        #NOTE: When setlocale is run with only the 1st parameter, it is a "get" not a "set" function.
449
        $locale = setlocale(LC_COLLATE);
450
    }
451
    my $collator = Unicode::Collate::Locale->new( locale => $locale );
452
    if ( $collator && $facets ) {
453
        my @sorted_facets = sort { $collator->cmp( $a->{facet_label_value}, $b->{facet_label_value} ) } @{$facets};
454
        if (@sorted_facets) {
455
            return \@sorted_facets;
456
        }
457
    }
458
459
    #NOTE: If there was a problem, at least return the not sorted facets
460
    return $facets;
461
}
462
463
430
=head2 _convert_facets
464
=head2 _convert_facets
431
465
432
    my $koha_facets = _convert_facets($es_facets);
466
    my $koha_facets = _convert_facets($es_facets);
Lines 504-511 sub _convert_facets { Link Here
504
            };
538
            };
505
        }
539
        }
506
        if( C4::Context->preference('FacetOrder') eq 'Alphabetical' ){
540
        if( C4::Context->preference('FacetOrder') eq 'Alphabetical' ){
507
            @{ $facet->{facets} } =
541
            my $sorted_facets = $self->_sort_facets( { facets => $facet->{facets} } );
508
                sort { $a->{facet_label_value} cmp $b->{facet_label_value} } @{ $facet->{facets} };
542
            if ($sorted_facets) {
543
                $facet->{facets} = $sorted_facets;
544
            }
509
        }
545
        }
510
        push @facets, $facet if exists $facet->{facets};
546
        push @facets, $facet if exists $facet->{facets};
511
    }
547
    }
(-)a/t/Koha/SearchEngine/Elasticsearch/Search.t (-2 / +68 lines)
Lines 17-28 Link Here
17
17
18
use Modern::Perl;
18
use Modern::Perl;
19
19
20
use Test::More tests => 2;
20
use Test::More tests => 3;
21
use Test::MockModule;
21
use Test::MockModule;
22
use t::lib::Mocks;
22
use t::lib::Mocks;
23
23
24
use utf8;
25
24
use_ok('Koha::SearchEngine::Elasticsearch::Search');
26
use_ok('Koha::SearchEngine::Elasticsearch::Search');
25
27
28
subtest '_sort_facets' => sub {
29
    plan tests => 2;
30
    t::lib::Mocks::mock_preference( 'SearchEngine', 'Elasticsearch' );
31
    my $facets = [
32
        { facet_label_value => 'Mary' },
33
        { facet_label_value => 'Harry' },
34
        { facet_label_value => 'Fairy' },
35
        { facet_label_value => 'Ari' },
36
        { facet_label_value => 'mary' },
37
        { facet_label_value => 'harry' },
38
        { facet_label_value => 'fairy' },
39
        { facet_label_value => 'ari' },
40
        { facet_label_value => 'étienne' },
41
        { facet_label_value => 'Åuthor' },
42
    ];
43
44
    my @normal_sort_facets     = sort { $a->{facet_label_value} cmp $b->{facet_label_value} } @$facets;
45
    my @normal_expected_facets = (
46
        { facet_label_value => 'Ari' },
47
        { facet_label_value => 'Fairy' },
48
        { facet_label_value => 'Harry' },
49
        { facet_label_value => 'Mary' },
50
        { facet_label_value => 'ari' },
51
        { facet_label_value => 'fairy' },
52
        { facet_label_value => 'harry' },
53
        { facet_label_value => 'mary' },
54
        { facet_label_value => 'Åuthor' },
55
        { facet_label_value => 'étienne' },
56
    );
57
58
    #NOTE: stringwise/bytewise is not UTF-8 friendly
59
    is_deeply( \@normal_sort_facets, \@normal_expected_facets, "Perl's built-in sort is stringwise/bytewise." );
60
61
    my $search = Koha::SearchEngine::Elasticsearch::Search->new(
62
        { index => $Koha::SearchEngine::Elasticsearch::AUTHORITIES_INDEX } );
63
64
    #NOTE: The 'default' locale uses the Default Unicode Collation Element Table, which
65
    #is used for the locales of English (en) and French (fr).
66
    my $sorted_facets = $search->_sort_facets( { facets => $facets, locale => 'default' } );
67
    my $expected      = [
68
        { facet_label_value => 'ari' },
69
        { facet_label_value => 'Ari' },
70
        { facet_label_value => 'Åuthor' },
71
        { facet_label_value => 'étienne' },
72
        { facet_label_value => 'fairy' },
73
        { facet_label_value => 'Fairy' },
74
        { facet_label_value => 'harry' },
75
        { facet_label_value => 'Harry' },
76
        { facet_label_value => 'mary' },
77
        { facet_label_value => 'Mary' },
78
    ];
79
    is_deeply( $sorted_facets, $expected, "Facets sorted correctly with default locale" );
80
81
    #NOTE: If "locale" is not provided to _sort_facets, it will look up the LC_COLLATE
82
    #for the local system. This is what allows this function to work well in production.
83
    #However, since LC_COLLATE could vary from system to system running these unit tests,
84
    #we can't test arbitrary locales here.
85
86
    #TODO: It would be great to explicitly use a fi_FI locale for another test, but we cannot guarantee
87
    #that every system has that locale. That said, perhaps we could do some conditional unit
88
    #testing if certain locales are available when running tests. This could allow for the Koha community
89
    #to thoroughly test this functionality, while letting anyone run the unit tests regardless of their
90
    #installed locales.
91
};
92
26
subtest 'search_auth_compat' => sub {
93
subtest 'search_auth_compat' => sub {
27
    plan tests => 4;
94
    plan tests => 4;
28
95
29
- 

Return to bug 36947