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

(-)a/Koha/Patron.pm (-4 / +31 lines)
Lines 1815-1830 sub has_valid_userid { Link Here
1815
1815
1816
=head3 generate_userid
1816
=head3 generate_userid
1817
1817
1818
my $patron = Koha::Patron->new( $params );
1818
    $patron->generate_userid;
1819
$patron->generate_userid
1820
1819
1821
Generate a userid using the $surname and the $firstname (if there is a value in $firstname).
1820
    If you do not have a plugin for generating a userid, we will call
1821
    the legacy method here that returns firstname.surname[.number],
1822
    where number is an optional suffix to make the userid unique.
1823
    (Its behavior has not been changed on bug 32426.)
1822
1824
1823
Set a generated userid ($firstname.$surname if there is a $firstname, or $surname if there is no value in $firstname) plus offset (0 if the $userid is unique, or a higher numeric value if not unique).
1825
    If you have plugin(s), the first valid response will be used.
1826
    A plugin is assumed to return a valid userid as suggestion, but not
1827
    assumed to save it already.
1828
    Does not fallback to legacy (you could arrange for that in your plugin).
1829
    Clears userid when there are no valid plugin responses.
1824
1830
1825
=cut
1831
=cut
1826
1832
1827
sub generate_userid {
1833
sub generate_userid {
1834
    my ( $self ) = @_;
1835
    my @responses = Koha::Plugins->call(
1836
        'patron_generate_userid', { patron => $self },
1837
    );
1838
    unless( @responses ) {
1839
        # Empty list only possible when there are NO enabled plugins for this method.
1840
        # In that case we provide legacy response.
1841
        return $self->_generate_userid_legacy;
1842
    }
1843
    # If a plugin returned false value or invalid value, we do however not return
1844
    # legacy response. The plugins should deal with that themselves. So we prevent
1845
    # unexpected/unwelcome legacy codes for plugin failures.
1846
    foreach my $response ( grep { $_ } @responses ) {
1847
        $self->userid( $response );
1848
        return $self if $self->has_valid_userid;
1849
    }
1850
    $self->userid(undef);
1851
    return $self;
1852
}
1853
1854
sub _generate_userid_legacy { # as we always did
1828
    my ($self) = @_;
1855
    my ($self) = @_;
1829
    my $offset = 0;
1856
    my $offset = 0;
1830
    my $firstname = $self->firstname // q{};
1857
    my $firstname = $self->firstname // q{};
(-)a/t/db_dependent/Koha/Patron_generate_userid.t (+158 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# Copyright 2022 Rijksmuseum, Koha development team
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
use utf8;
22
#use Data::Dumper;
23
use Test::More tests => 2;
24
use Test::Warn;
25
use Test::MockModule;
26
use Test::MockObject;
27
28
use t::lib::Mocks;
29
use t::lib::TestBuilder;
30
31
use Koha::Database;
32
use Koha::Patrons;
33
use Koha::Plugins;
34
35
our $schema = Koha::Database->new->schema;
36
$schema->storage->txn_begin;
37
our $builder = t::lib::TestBuilder->new;
38
our $expected_plugins = [];
39
40
sub mockedGetPlugins {
41
    my @plugins;
42
    foreach my $p ( @$expected_plugins ) {
43
        my $object = Test::MockObject->new;
44
        my $method;
45
        if( $p eq 'email' ) {
46
            $method = sub { return $_[1]->{patron}->email; };
47
        } elsif( $p eq 'firstname' ) {
48
            $method = sub { return $_[1]->{patron}->firstname. ($_[1]->{patron}->id // 0); };
49
        } elsif( $p eq 'baduserid' ) {
50
            $method = sub { return ''; }; # bad return
51
        } elsif( $p eq 'die' ) {
52
            $method = sub { die; };
53
        } elsif( $p eq 'undef' ) {
54
            $method = sub { return; };
55
        } else { # borrowernumber
56
            $method = sub { return $_[1]->{patron}->id // 0; };
57
        }
58
        $object->mock('patron_generate_userid', $method);
59
        $object->mock('get_metadata', sub { return { name => $p }}); # called when warning from ->call
60
        push @plugins, $object;
61
    }
62
    return @plugins;
63
}
64
65
subtest 'generate_userid (legacy, without plugins)' => sub {
66
    plan tests => 7;
67
68
    t::lib::Mocks::mock_config('enable_plugins', 0);
69
70
    my $library = $builder->build_object( { class => 'Koha::Libraries' } );
71
    my $patron_category = $builder->build_object(
72
        {
73
            class => 'Koha::Patron::Categories',
74
            value => { category_type => 'P', enrolmentfee => 0 }
75
        }
76
    );
77
    my %data = (
78
        cardnumber   => "123456789",
79
        firstname    => "Tômàsító",
80
        surname      => "Ñoné",
81
        categorycode => $patron_category->categorycode,
82
        branchcode   => $library->branchcode,
83
    );
84
85
    my $expected_userid_patron_1 = 'tomasito.none';
86
    my $new_patron = Koha::Patron->new({ firstname => $data{firstname}, surname => $data{surname} } );
87
    $new_patron->generate_userid;
88
    my $userid = $new_patron->userid;
89
    is( $userid, $expected_userid_patron_1, 'generate_userid should generate the userid we expect' );
90
    my $borrowernumber = Koha::Patron->new(\%data)->store->borrowernumber;
91
    my $patron_1 = Koha::Patrons->find($borrowernumber);
92
    is ( $patron_1->userid, $expected_userid_patron_1, 'The userid generated should be the one we expect' );
93
94
    $new_patron->generate_userid;
95
    $userid = $new_patron->userid;
96
    is( $userid, $expected_userid_patron_1 . '1', 'generate_userid should generate the userid we expect' );
97
    $data{cardnumber} = '987654321';
98
    my $new_borrowernumber = Koha::Patron->new(\%data)->store->borrowernumber;
99
    my $patron_2 = Koha::Patrons->find($new_borrowernumber);
100
    isnt( $patron_2->userid, 'tomasito',
101
        "Patron with duplicate userid has new userid generated" );
102
    is( $patron_2->userid, $expected_userid_patron_1 . '1', # TODO we could make that configurable
103
        "Patron with duplicate userid has new userid generated (1 is appended" );
104
105
    $new_patron->generate_userid;
106
    $userid = $new_patron->userid;
107
    is( $userid, $expected_userid_patron_1 . '2', 'generate_userid should generate the userid we expect' );
108
109
    $patron_1 = Koha::Patrons->find($borrowernumber);
110
    $patron_1->userid(undef);
111
    $patron_1->generate_userid;
112
    $userid = $patron_1->userid;
113
    is( $userid, $expected_userid_patron_1, 'generate_userid should generate the userid we expect' );
114
115
    # Cleanup
116
    $patron_1->delete;
117
    $patron_2->delete;
118
};
119
120
subtest 'Plugins for generate_userid' => sub {
121
    plan tests => 6;
122
    t::lib::Mocks::mock_config('enable_plugins', 1);
123
124
    my $auth = Test::MockModule->new( 'Koha::Plugins' );
125
    $auth->mock( 'GetPlugins', \&mockedGetPlugins );
126
    $auth->mock( 'get_enabled_plugins', \&mockedGetPlugins );
127
128
    # Check the email plugin
129
    $expected_plugins = [ 'email' ];
130
    my $patron1 = $builder->build_object({ class => 'Koha::Patrons', value => { email => 'test@domain.com' } });
131
    $patron1->generate_userid;
132
    is( $patron1->userid, 'test@domain.com', 'generated userid from email plugin' );
133
134
    # Expect second response from firstname, because empty string from baduserid is not valid
135
    $expected_plugins = [ 'baduserid', 'firstname', 'email' ];
136
    $patron1->generate_userid;
137
    my $reg = $patron1->firstname. '\d+';
138
    like( $patron1->userid, qr/$reg/, 'ignored baduserid, generated userid from firstname plugin' );
139
140
    # Expect third response from fallback for wrong_method, catch warning from die plugin
141
    $expected_plugins = [ 'die', 'baduserid', 'wrong_method', 'firstname', 'email' ];
142
    warning_like { $patron1->generate_userid; } qr/Plugin error \(die\): Died/, 'Caught warn for die plugin';
143
    like( $patron1->userid, qr/^\d+$/, 'generated borrowernumber userid from plugin when given wrong_method' );
144
    $patron1->delete;
145
146
    # Testing with an object not in storage; unknown should return id 0, the plugin undef returns undef :)
147
    $expected_plugins = [ 'unknown', 'undef' ];
148
    $patron1= Koha::Patron->new({ firstname => 'A', surname => 'B', email => 'test2@domain.com', userid => 'user999' });
149
    $patron1->generate_userid;
150
    is( $patron1->userid, undef, 'No valid plugin responses' );
151
152
    # Finally pass no plugins, so we would expect legacy response
153
    $expected_plugins = [];
154
    $patron1->generate_userid;
155
    is( $patron1->userid, 'a.b', 'No plugins: legacy response' );
156
};
157
158
$schema->storage->txn_rollback;
(-)a/t/db_dependent/Koha/Patrons.t (-55 / +1 lines)
Lines 19-25 Link Here
19
19
20
use Modern::Perl;
20
use Modern::Perl;
21
21
22
use Test::More tests => 45;
22
use Test::More tests => 44;
23
use Test::Warn;
23
use Test::Warn;
24
use Test::Exception;
24
use Test::Exception;
25
use Test::MockModule;
25
use Test::MockModule;
Lines 1599-1657 subtest 'userid_is_valid' => sub { Link Here
1599
    $patron_3->delete;
1599
    $patron_3->delete;
1600
};
1600
};
1601
1601
1602
subtest 'generate_userid' => sub {
1603
    plan tests => 7;
1604
1605
    my $library = $builder->build_object( { class => 'Koha::Libraries' } );
1606
    my $patron_category = $builder->build_object(
1607
        {
1608
            class => 'Koha::Patron::Categories',
1609
            value => { category_type => 'P', enrolmentfee => 0 }
1610
        }
1611
    );
1612
    my %data = (
1613
        cardnumber   => "123456789",
1614
        firstname    => "Tômàsító",
1615
        surname      => "Ñoné",
1616
        categorycode => $patron_category->categorycode,
1617
        branchcode   => $library->branchcode,
1618
    );
1619
1620
    my $expected_userid_patron_1 = 'tomasito.none';
1621
    my $new_patron = Koha::Patron->new({ firstname => $data{firstname}, surname => $data{surname} } );
1622
    $new_patron->generate_userid;
1623
    my $userid = $new_patron->userid;
1624
    is( $userid, $expected_userid_patron_1, 'generate_userid should generate the userid we expect' );
1625
    my $borrowernumber = Koha::Patron->new(\%data)->store->borrowernumber;
1626
    my $patron_1 = Koha::Patrons->find($borrowernumber);
1627
    is ( $patron_1->userid, $expected_userid_patron_1, 'The userid generated should be the one we expect' );
1628
1629
    $new_patron->generate_userid;
1630
    $userid = $new_patron->userid;
1631
    is( $userid, $expected_userid_patron_1 . '1', 'generate_userid should generate the userid we expect' );
1632
    $data{cardnumber} = '987654321';
1633
    my $new_borrowernumber = Koha::Patron->new(\%data)->store->borrowernumber;
1634
    my $patron_2 = Koha::Patrons->find($new_borrowernumber);
1635
    isnt( $patron_2->userid, 'tomasito',
1636
        "Patron with duplicate userid has new userid generated" );
1637
    is( $patron_2->userid, $expected_userid_patron_1 . '1', # TODO we could make that configurable
1638
        "Patron with duplicate userid has new userid generated (1 is appened" );
1639
1640
    $new_patron->generate_userid;
1641
    $userid = $new_patron->userid;
1642
    is( $userid, $expected_userid_patron_1 . '2', 'generate_userid should generate the userid we expect' );
1643
1644
    $patron_1 = Koha::Patrons->find($borrowernumber);
1645
    $patron_1->userid(undef);
1646
    $patron_1->generate_userid;
1647
    $userid = $patron_1->userid;
1648
    is( $userid, $expected_userid_patron_1, 'generate_userid should generate the userid we expect' );
1649
1650
    # Cleanup
1651
    $patron_1->delete;
1652
    $patron_2->delete;
1653
};
1654
1655
$nb_of_patrons = Koha::Patrons->search->count;
1602
$nb_of_patrons = Koha::Patrons->search->count;
1656
$retrieved_patron_1->delete;
1603
$retrieved_patron_1->delete;
1657
is( Koha::Patrons->search->count, $nb_of_patrons - 1, 'Delete should have deleted the patron' );
1604
is( Koha::Patrons->search->count, $nb_of_patrons - 1, 'Delete should have deleted the patron' );
1658
- 

Return to bug 32426