Lines 19-27
use Modern::Perl;
Link Here
|
19 |
|
19 |
|
20 |
use CGI qw ( -utf8 ); |
20 |
use CGI qw ( -utf8 ); |
21 |
use Digest::MD5 qw( md5_base64 md5_hex ); |
21 |
use Digest::MD5 qw( md5_base64 md5_hex ); |
|
|
22 |
use List::MoreUtils qw( each_array uniq ); |
22 |
use String::Random qw( random_string ); |
23 |
use String::Random qw( random_string ); |
23 |
|
24 |
|
24 |
use C4::Auth; |
25 |
use C4::Auth; |
|
|
26 |
use C4::Koha qw( GetAuthorisedValueByCode ); |
25 |
use C4::Output; |
27 |
use C4::Output; |
26 |
use C4::Members; |
28 |
use C4::Members; |
27 |
use C4::Form::MessagingPreferences; |
29 |
use C4::Form::MessagingPreferences; |
Lines 72-77
$template->param(
Link Here
|
72 |
OPACPatronDetails => C4::Context->preference('OPACPatronDetails'), |
74 |
OPACPatronDetails => C4::Context->preference('OPACPatronDetails'), |
73 |
); |
75 |
); |
74 |
|
76 |
|
|
|
77 |
my $attributes = ParsePatronAttributes($cgi); |
78 |
my $conflicting_attribute = 0; |
79 |
|
80 |
foreach my $attr (@$attributes) { |
81 |
unless ( C4::Members::Attributes::CheckUniqueness($attr->{code}, $attr->{value}, $borrowernumber) ) { |
82 |
my $attr_info = C4::Members::AttributeTypes->fetch($attr->{code}); |
83 |
$template->param( |
84 |
extended_unique_id_failed_code => $attr->{code}, |
85 |
extended_unique_id_failed_value => $attr->{value}, |
86 |
extended_unique_id_failed_description => $attr_info->description() |
87 |
); |
88 |
$conflicting_attribute = 1; |
89 |
} |
90 |
} |
91 |
|
75 |
if ( $action eq 'create' ) { |
92 |
if ( $action eq 'create' ) { |
76 |
|
93 |
|
77 |
my %borrower = ParseCgiForBorrower($cgi); |
94 |
my %borrower = ParseCgiForBorrower($cgi); |
Lines 81-92
if ( $action eq 'create' ) {
Link Here
|
81 |
my @empty_mandatory_fields = CheckMandatoryFields( \%borrower, $action ); |
98 |
my @empty_mandatory_fields = CheckMandatoryFields( \%borrower, $action ); |
82 |
my $invalidformfields = CheckForInvalidFields(\%borrower); |
99 |
my $invalidformfields = CheckForInvalidFields(\%borrower); |
83 |
|
100 |
|
84 |
if (@empty_mandatory_fields || @$invalidformfields) { |
101 |
if (@empty_mandatory_fields || @$invalidformfields || $conflicting_attribute) { |
85 |
$template->param( |
102 |
$template->param( |
86 |
empty_mandatory_fields => \@empty_mandatory_fields, |
103 |
empty_mandatory_fields => \@empty_mandatory_fields, |
87 |
invalid_form_fields => $invalidformfields, |
104 |
invalid_form_fields => $invalidformfields, |
88 |
borrower => \%borrower |
105 |
borrower => \%borrower |
89 |
); |
106 |
); |
|
|
107 |
$template->param( patron_attribute_classes => GeneratePatronAttributesForm( undef, $attributes ) ); |
90 |
} |
108 |
} |
91 |
elsif ( |
109 |
elsif ( |
92 |
md5_base64( $cgi->param('captcha') ) ne $cgi->param('captcha_digest') ) |
110 |
md5_base64( $cgi->param('captcha') ) ne $cgi->param('captcha_digest') ) |
Lines 95-100
if ( $action eq 'create' ) {
Link Here
|
95 |
failed_captcha => 1, |
113 |
failed_captcha => 1, |
96 |
borrower => \%borrower |
114 |
borrower => \%borrower |
97 |
); |
115 |
); |
|
|
116 |
$template->param( patron_attribute_classes => GeneratePatronAttributesForm( undef, $attributes ) ); |
98 |
} |
117 |
} |
99 |
else { |
118 |
else { |
100 |
if ( |
119 |
if ( |
Lines 152-157
if ( $action eq 'create' ) {
Link Here
|
152 |
C4::Context->preference('OpacPasswordChange') ); |
171 |
C4::Context->preference('OpacPasswordChange') ); |
153 |
|
172 |
|
154 |
my ( $borrowernumber, $password ) = AddMember_Opac(%borrower); |
173 |
my ( $borrowernumber, $password ) = AddMember_Opac(%borrower); |
|
|
174 |
C4::Members::Attributes::SetBorrowerAttributes( $borrowernumber, $attributes ); |
155 |
C4::Form::MessagingPreferences::handle_form_action($cgi, { borrowernumber => $borrowernumber }, $template, 1, C4::Context->preference('PatronSelfRegistrationDefaultCategory') ) if $borrowernumber && C4::Context->preference('EnhancedMessagingPreferences'); |
175 |
C4::Form::MessagingPreferences::handle_form_action($cgi, { borrowernumber => $borrowernumber }, $template, 1, C4::Context->preference('PatronSelfRegistrationDefaultCategory') ) if $borrowernumber && C4::Context->preference('EnhancedMessagingPreferences'); |
156 |
|
176 |
|
157 |
$template->param( password_cleartext => $password ); |
177 |
$template->param( password_cleartext => $password ); |
Lines 174-185
elsif ( $action eq 'update' ) {
Link Here
|
174 |
CheckMandatoryFields( \%borrower_changes, $action ); |
194 |
CheckMandatoryFields( \%borrower_changes, $action ); |
175 |
my $invalidformfields = CheckForInvalidFields(\%borrower); |
195 |
my $invalidformfields = CheckForInvalidFields(\%borrower); |
176 |
|
196 |
|
177 |
if (@empty_mandatory_fields || @$invalidformfields) { |
197 |
if (@empty_mandatory_fields || @$invalidformfields || $conflicting_attribute) { |
178 |
$template->param( |
198 |
$template->param( |
179 |
empty_mandatory_fields => \@empty_mandatory_fields, |
199 |
empty_mandatory_fields => \@empty_mandatory_fields, |
180 |
invalid_form_fields => $invalidformfields, |
200 |
invalid_form_fields => $invalidformfields, |
181 |
borrower => \%borrower |
201 |
borrower => \%borrower |
182 |
); |
202 |
); |
|
|
203 |
$template->param( patron_attribute_classes => GeneratePatronAttributesForm( undef, $attributes ) ); |
183 |
|
204 |
|
184 |
$template->param( action => 'edit' ); |
205 |
$template->param( action => 'edit' ); |
185 |
} |
206 |
} |
Lines 217-230
elsif ( $action eq 'update' ) {
Link Here
|
217 |
elsif ( $action eq 'edit' ) { #Display logged in borrower's data |
238 |
elsif ( $action eq 'edit' ) { #Display logged in borrower's data |
218 |
my $borrower = GetMember( borrowernumber => $borrowernumber ); |
239 |
my $borrower = GetMember( borrowernumber => $borrowernumber ); |
219 |
|
240 |
|
220 |
if (C4::Context->preference('ExtendedPatronAttributes')) { |
|
|
221 |
my $attributes = C4::Members::Attributes::GetBorrowerAttributes($borrowernumber, 'opac'); |
222 |
if (scalar(@$attributes) > 0) { |
223 |
$borrower->{ExtendedPatronAttributes} = 1; |
224 |
$borrower->{patron_attributes} = $attributes; |
225 |
} |
226 |
} |
227 |
|
228 |
$template->param( |
241 |
$template->param( |
229 |
borrower => $borrower, |
242 |
borrower => $borrower, |
230 |
guarantor => Koha::Borrowers->find($borrowernumber)->guarantor(), |
243 |
guarantor => Koha::Borrowers->find($borrowernumber)->guarantor(), |
Lines 239-244
elsif ( $action eq 'edit' ) { #Display logged in borrower's data
Link Here
|
239 |
} |
252 |
} |
240 |
} |
253 |
} |
241 |
|
254 |
|
|
|
255 |
$template->param( patron_attribute_classes => GeneratePatronAttributesForm( $borrower ) ); |
256 |
} else { |
257 |
$template->param( patron_attribute_classes => GeneratePatronAttributesForm() ); |
242 |
} |
258 |
} |
243 |
|
259 |
|
244 |
my $captcha = random_string("CCCCC"); |
260 |
my $captcha = random_string("CCCCC"); |
Lines 373-375
sub DelEmptyFields {
Link Here
|
373 |
|
389 |
|
374 |
return %borrower; |
390 |
return %borrower; |
375 |
} |
391 |
} |
376 |
- |
392 |
|
|
|
393 |
sub GeneratePatronAttributesForm { |
394 |
my ( $borrower, $entered_attributes ) = @_; |
395 |
|
396 |
use Data::Dumper; warn Dumper( $entered_attributes ); |
397 |
|
398 |
# Get all attribute types and the values for this patron (if applicable) |
399 |
my @types = C4::Members::AttributeTypes::GetAttributeTypes(); |
400 |
|
401 |
if (scalar(@types) == 0) { |
402 |
return []; |
403 |
} |
404 |
|
405 |
my %attr_values = (); |
406 |
|
407 |
if ( $borrower ) { |
408 |
my $attributes = C4::Members::Attributes::GetBorrowerAttributes($borrowernumber); |
409 |
|
410 |
# Remap the patron's attributes into a hash of arrayrefs per attribute (depends on |
411 |
# autovivification) |
412 |
foreach my $attr (@$attributes) { |
413 |
push @{ $attr_values{ $attr->{code} } }, $attr; |
414 |
} |
415 |
} |
416 |
|
417 |
if ( $entered_attributes ) { |
418 |
foreach my $attr (@$entered_attributes) { |
419 |
push @{ $attr_values{ $attr->{code} } }, $attr; |
420 |
} |
421 |
} |
422 |
|
423 |
# Find all existing classes |
424 |
my @classes = uniq( map { $_->{class} } @types ); |
425 |
@classes = sort @classes; |
426 |
my %items_by_class; |
427 |
|
428 |
foreach my $attr_type_desc (@types) { |
429 |
my $attr_type = C4::Members::AttributeTypes->fetch( $attr_type_desc->{code} ); |
430 |
# Make sure this attribute should be displayed in the OPAC |
431 |
next unless ( $attr_type->opac_display() ); |
432 |
# Then, make sure it either has values or is editable |
433 |
next unless ( $attr_values{ $attr_type->code() } || $attr_type->opac_editable() ); |
434 |
|
435 |
push @{ $items_by_class{ $attr_type->class() } }, { |
436 |
type => $attr_type, |
437 |
# If editable, make sure there's at least one empty entry, to make the template's job easier |
438 |
values => $attr_values{ $attr_type->code() } || [{}] |
439 |
}; |
440 |
} |
441 |
|
442 |
use Data::Dumper; warn Dumper( \%items_by_class ); |
443 |
|
444 |
# Finally, build a list of containing classes |
445 |
my @class_loop; |
446 |
foreach my $class (@classes) { |
447 |
next unless ( $items_by_class{$class} ); |
448 |
|
449 |
my $lib = GetAuthorisedValueByCode( 'PA_CLASS', $class, 1 ) || $class; |
450 |
push @class_loop, { |
451 |
class => $class, |
452 |
items => $items_by_class{$class}, |
453 |
lib => $lib, |
454 |
}; |
455 |
} |
456 |
|
457 |
return \@class_loop; |
458 |
} |
459 |
|
460 |
sub ParsePatronAttributes { |
461 |
my ( $cgi ) = @_; |
462 |
|
463 |
my @codes = $cgi->param('patron_attribute_code'); |
464 |
my @values = $cgi->param('patron_attribute_value'); |
465 |
my @passwords = $cgi->param('patron_attribute_password'); |
466 |
|
467 |
my $ea = each_array( @codes, @values, @passwords ); |
468 |
my @attributes; |
469 |
my %dups = (); |
470 |
|
471 |
while ( my ( $code, $value, $password ) = $ea->() ) { |
472 |
next unless defined($value) and $value ne ''; |
473 |
next if exists $dups{$code}->{$value}; |
474 |
$dups{$code}->{$value} = 1; |
475 |
|
476 |
push @attributes, { code => $code, value => $value, password => $password }; |
477 |
} |
478 |
|
479 |
return \@attributes; |
480 |
} |