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

(-)a/C4/Members/Attributes.pm (-44 / +2 lines)
Lines 31-37 our ($csv, $AttributeTypes); Link Here
31
BEGIN {
31
BEGIN {
32
    @ISA = qw(Exporter);
32
    @ISA = qw(Exporter);
33
    @EXPORT_OK = qw(
33
    @EXPORT_OK = qw(
34
                    extended_attributes_code_value_arrayref extended_attributes_merge
34
                    extended_attributes_code_value_arrayref
35
                    );
35
                    );
36
    %EXPORT_TAGS = ( all => \@EXPORT_OK );
36
    %EXPORT_TAGS = ( all => \@EXPORT_OK );
37
}
37
}
Lines 61-66 Caches Text::CSV parser object for efficiency. Link Here
61
61
62
sub extended_attributes_code_value_arrayref {
62
sub extended_attributes_code_value_arrayref {
63
    my $string = shift or return;
63
    my $string = shift or return;
64
    use Data::Printer colored => 1; warn p $string;
64
    $csv or $csv = Text::CSV->new({binary => 1});  # binary needed for non-ASCII Unicode
65
    $csv or $csv = Text::CSV->new({binary => 1});  # binary needed for non-ASCII Unicode
65
    my $ok   = $csv->parse($string);  # parse field again to get subfields!
66
    my $ok   = $csv->parse($string);  # parse field again to get subfields!
66
    my @list = $csv->fields();
67
    my @list = $csv->fields();
Lines 73-121 sub extended_attributes_code_value_arrayref { Link Here
73
    # nested map because of split
74
    # nested map because of split
74
}
75
}
75
76
76
=head2 extended_attributes_merge
77
78
  my $old_attributes = extended_attributes_code_value_arrayref("homeroom:224,grade:04,deanslist:2007,deanslist:2008,somedata:xxx");
79
  my $new_attributes = extended_attributes_code_value_arrayref("homeroom:115,grade:05,deanslist:2009,extradata:foobar");
80
  my $merged = extended_attributes_merge($patron_attributes, $new_attributes, 1);
81
82
  # assuming deanslist is a repeatable code, value same as:
83
  # $merged = extended_attributes_code_value_arrayref("homeroom:115,grade:05,deanslist:2007,deanslist:2008,deanslist:2009,extradata:foobar,somedata:xxx");
84
85
Takes three arguments.  The first two are references to array of hashrefs, each like:
86
 [ { code => 'CODE', value => 'value' }, { code => 'CODE2', value => 'othervalue' } ... ]
87
88
The third option specifies whether repeatable codes are clobbered or collected.  True for non-clobber.
89
90
Returns one reference to (merged) array of hashref.
91
92
Caches results of attribute types for efficiency. # FIXME That is very bad and can cause side-effects undef plack
93
94
=cut
95
96
sub extended_attributes_merge {
97
    my $old = shift or return;
98
    my $new = shift or return $old;
99
    my $keep = @_ ? shift : 0;
100
    $AttributeTypes or $AttributeTypes = Koha::Patron::Attribute::Types->search->unblessed;
101
    my @merged = @$old;
102
    foreach my $att (@$new) {
103
        unless ($att->{code}) {
104
            warn "Cannot merge element: no 'code' defined";
105
            next;
106
        }
107
        unless ($AttributeTypes->{$att->{code}}) {
108
            warn "Cannot merge element: unrecognized code = '$att->{code}'";
109
            next;
110
        }
111
        unless ($AttributeTypes->{$att->{code}}->{repeatable} and $keep) {
112
            @merged = grep {$att->{code} ne $_->{code}} @merged;    # filter out any existing attributes of the same code
113
        }
114
        push @merged, $att;
115
    }
116
    return [( sort {&_sort_by_code($a,$b)} @merged )];
117
}
118
119
sub _sort_by_code {
77
sub _sort_by_code {
120
    my ($x, $y) = @_;
78
    my ($x, $y) = @_;
121
    defined ($x->{code}) or return -1;
79
    defined ($x->{code}) or return -1;
(-)a/Koha/Patron/Attributes.pm (+28 lines)
Lines 87-92 sub filter_by_branch_limitations { Link Here
87
    return $self->search( $or, $join );
87
    return $self->search( $or, $join );
88
}
88
}
89
89
90
sub merge_with {
91
    my ( $self, $new_attributes ) = @_;
92
93
    my @merged = $self->as_list;
94
    while ( my ( $attr ) = $new_attributes->next ) {
95
        unless ( $attr->code ) {
96
            warn "Cannot merge element: no 'code' defined";
97
            next;
98
        }
99
100
        # FIXME Do we need that here or let ->store do the job?
101
        unless ( $attr->type ) {
102
            warn "Cannot merge element: unrecognized code = '$attr->code'";
103
            next;
104
        }
105
        unless ( $attr->type->repeatable ) {
106
            # filter out any existing attributes of the same code
107
            @merged = grep {$attr->code ne $_->code} @merged;
108
        }
109
110
        push @merged, $attr;
111
    }
112
113
    # WARNING - we would like to return a set, but $new_attributes is not in storage yet
114
    # Maybe there is something obvious I (JD) am missing
115
    return [ sort { $a->{code} cmp $b->{code} || $a->{attribute} cmp $b->{attribute} } @merged ];
116
}
117
90
=head3 _type
118
=head3 _type
91
119
92
=cut
120
=cut
(-)a/Koha/Patrons/Import.pm (-1 / +2 lines)
Lines 290-296 sub import_patrons { Link Here
290
            if ($extended) {
290
            if ($extended) {
291
                if ($ext_preserve) {
291
                if ($ext_preserve) {
292
                    my $old_attributes = $patron->extended_attributes->as_list;
292
                    my $old_attributes = $patron->extended_attributes->as_list;
293
                    $patron_attributes = extended_attributes_merge( $old_attributes, $patron_attributes );
293
294
                    $patron_attributes = $patron->extended_attributes->merge_with( $patron_attributes );
294
                }
295
                }
295
                eval {
296
                eval {
296
                    # We do not want to filter by branch, maybe we should?
297
                    # We do not want to filter by branch, maybe we should?
(-)a/t/Members_Attributes.t (-99 lines)
Lines 1-98 Link Here
1
#!/usr/bin/perl
2
#
3
#
4
5
use strict;
6
use warnings;
7
8
use Test::More tests => 11;
9
10
BEGIN {
11
    use_ok('C4::Members::Attributes', qw(:all));
12
}
13
14
INIT {
15
    $C4::Members::Attributes::AttributeTypes = {
16
          'grade' => {
17
                       'opac_display' => '1',
18
                       'staff_searchable' => '1',
19
                       'description' => 'Grade level',
20
                       'authorised_value_category' => '',
21
                       'repeatable' => '0',
22
                       'code' => 'grade',
23
                       'unique_id' => '0'
24
                     },
25
          'deanslist' => {
26
                           'opac_display' => '0',
27
                           'staff_searchable' => '1',
28
                           'description' => 'Deans List (annual)',
29
                           'authorised_value_category' => '',
30
                           'repeatable' => '1',
31
                           'code' => 'deanslist',
32
                           'unique_id' => '0'
33
                         },
34
          'somedata' => {
35
                           'opac_display' => '0',
36
                           'staff_searchable' => '0',
37
                           'description' => 'Some Ext. Attribute',
38
                           'authorised_value_category' => '',
39
                           'repeatable' => '0',
40
                           'code' => 'somedata',
41
                           'unique_id' => '0'
42
                         },
43
          'extradata' => {
44
                           'opac_display' => '0',
45
                           'staff_searchable' => '0',
46
                           'description' => 'Another Ext. Attribute',
47
                           'authorised_value_category' => '',
48
                           'repeatable' => '0',
49
                           'code' => 'extradata',
50
                           'unique_id' => '0'
51
                         },
52
          'school_id' => {
53
                           'opac_display' => '1',
54
                           'staff_searchable' => '1',
55
                           'description' => 'School ID Number',
56
                           'authorised_value_category' => '',
57
                           'repeatable' => '0',
58
                           'code' => 'school_id',
59
                           'unique_id' => '1'
60
                         },
61
          'homeroom' => {
62
                          'opac_display' => '1',
63
                          'staff_searchable' => '1',
64
                          'description' => 'Homeroom',
65
                          'authorised_value_category' => '',
66
                          'repeatable' => '0',
67
                          'code' => 'homeroom',
68
                          'unique_id' => '0'
69
                        }
70
    };  # This is important to prevent extended_attributes_merge from touching DB.
71
}
72
73
74
my @merge_tests = (
75
    {
76
        line1 => "homeroom:501",
77
        line2 => "grade:01",
78
        merge => "homeroom:501,grade:01",
79
    },
80
    {
81
        line1 => "homeroom:224,grade:04,deanslist:2008,deanslist:2007,somedata:xxx",
82
        line2 => "homeroom:115,grade:05,deanslist:2009,extradata:foobar",
83
        merge => "homeroom:115,grade:05,deanslist:2008,deanslist:2007,deanslist:2009,extradata:foobar,somedata:xxx",
84
    },
85
);
86
87
can_ok('C4::Members::Attributes', qw(extended_attributes_merge extended_attributes_code_value_arrayref));
88
89
ok(ref($C4::Members::Attributes::AttributeTypes) eq 'HASH', '$C4::Members::Attributes::AttributeTypes is a hashref');
90
91
foreach my $test (@merge_tests) {
92
    my ($old, $new, $merged);
93
    ok($old = extended_attributes_code_value_arrayref($test->{line1}), "extended_attributes_code_value_arrayref('$test->{line1}')");
94
    ok($new = extended_attributes_code_value_arrayref($test->{line2}), "extended_attributes_code_value_arrayref('$test->{line2}')");
95
    ok($merged = extended_attributes_merge($old, $new),                "extended_attributes_merge(\$old, \$new)");
96
    ok($merged = extended_attributes_merge($old, $new, 1),             "extended_attributes_merge(\$old, \$new, 1)");
97
}
98
99
- 

Return to bug 20443