|
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 70-75
$template->param(
Link Here
|
| 70 |
OPACPatronDetails => C4::Context->preference('OPACPatronDetails'), |
72 |
OPACPatronDetails => C4::Context->preference('OPACPatronDetails'), |
| 71 |
); |
73 |
); |
| 72 |
|
74 |
|
|
|
75 |
my $attributes = ParsePatronAttributes($cgi); |
| 76 |
my $conflicting_attribute = 0; |
| 77 |
|
| 78 |
foreach my $attr (@$attributes) { |
| 79 |
unless ( C4::Members::Attributes::CheckUniqueness($attr->{code}, $attr->{value}, $borrowernumber) ) { |
| 80 |
my $attr_info = C4::Members::AttributeTypes->fetch($attr->{code}); |
| 81 |
$template->param( |
| 82 |
extended_unique_id_failed_code => $attr->{code}, |
| 83 |
extended_unique_id_failed_value => $attr->{value}, |
| 84 |
extended_unique_id_failed_description => $attr_info->description() |
| 85 |
); |
| 86 |
$conflicting_attribute = 1; |
| 87 |
} |
| 88 |
} |
| 89 |
|
| 73 |
if ( $action eq 'create' ) { |
90 |
if ( $action eq 'create' ) { |
| 74 |
|
91 |
|
| 75 |
my %borrower = ParseCgiForBorrower($cgi); |
92 |
my %borrower = ParseCgiForBorrower($cgi); |
|
Lines 79-90
if ( $action eq 'create' ) {
Link Here
|
| 79 |
my @empty_mandatory_fields = CheckMandatoryFields( \%borrower, $action ); |
96 |
my @empty_mandatory_fields = CheckMandatoryFields( \%borrower, $action ); |
| 80 |
my $invalidformfields = CheckForInvalidFields(\%borrower); |
97 |
my $invalidformfields = CheckForInvalidFields(\%borrower); |
| 81 |
|
98 |
|
| 82 |
if (@empty_mandatory_fields || @$invalidformfields) { |
99 |
if (@empty_mandatory_fields || @$invalidformfields || $conflicting_attribute) { |
| 83 |
$template->param( |
100 |
$template->param( |
| 84 |
empty_mandatory_fields => \@empty_mandatory_fields, |
101 |
empty_mandatory_fields => \@empty_mandatory_fields, |
| 85 |
invalid_form_fields => $invalidformfields, |
102 |
invalid_form_fields => $invalidformfields, |
| 86 |
borrower => \%borrower |
103 |
borrower => \%borrower |
| 87 |
); |
104 |
); |
|
|
105 |
$template->param( patron_attribute_classes => GeneratePatronAttributesForm( undef, $attributes ) ); |
| 88 |
} |
106 |
} |
| 89 |
elsif ( |
107 |
elsif ( |
| 90 |
md5_base64( $cgi->param('captcha') ) ne $cgi->param('captcha_digest') ) |
108 |
md5_base64( $cgi->param('captcha') ) ne $cgi->param('captcha_digest') ) |
|
Lines 93-98
if ( $action eq 'create' ) {
Link Here
|
| 93 |
failed_captcha => 1, |
111 |
failed_captcha => 1, |
| 94 |
borrower => \%borrower |
112 |
borrower => \%borrower |
| 95 |
); |
113 |
); |
|
|
114 |
$template->param( patron_attribute_classes => GeneratePatronAttributesForm( undef, $attributes ) ); |
| 96 |
} |
115 |
} |
| 97 |
else { |
116 |
else { |
| 98 |
if ( |
117 |
if ( |
|
Lines 150-155
if ( $action eq 'create' ) {
Link Here
|
| 150 |
C4::Context->preference('OpacPasswordChange') ); |
169 |
C4::Context->preference('OpacPasswordChange') ); |
| 151 |
|
170 |
|
| 152 |
my ( $borrowernumber, $password ) = AddMember_Opac(%borrower); |
171 |
my ( $borrowernumber, $password ) = AddMember_Opac(%borrower); |
|
|
172 |
C4::Members::Attributes::SetBorrowerAttributes( $borrowernumber, $attributes ); |
| 153 |
C4::Form::MessagingPreferences::handle_form_action($cgi, { borrowernumber => $borrowernumber }, $template, 1, C4::Context->preference('PatronSelfRegistrationDefaultCategory') ) if $borrowernumber && C4::Context->preference('EnhancedMessagingPreferences'); |
173 |
C4::Form::MessagingPreferences::handle_form_action($cgi, { borrowernumber => $borrowernumber }, $template, 1, C4::Context->preference('PatronSelfRegistrationDefaultCategory') ) if $borrowernumber && C4::Context->preference('EnhancedMessagingPreferences'); |
| 154 |
|
174 |
|
| 155 |
$template->param( password_cleartext => $password ); |
175 |
$template->param( password_cleartext => $password ); |
|
Lines 172-183
elsif ( $action eq 'update' ) {
Link Here
|
| 172 |
CheckMandatoryFields( \%borrower_changes, $action ); |
192 |
CheckMandatoryFields( \%borrower_changes, $action ); |
| 173 |
my $invalidformfields = CheckForInvalidFields(\%borrower); |
193 |
my $invalidformfields = CheckForInvalidFields(\%borrower); |
| 174 |
|
194 |
|
| 175 |
if (@empty_mandatory_fields || @$invalidformfields) { |
195 |
if (@empty_mandatory_fields || @$invalidformfields || $conflicting_attribute) { |
| 176 |
$template->param( |
196 |
$template->param( |
| 177 |
empty_mandatory_fields => \@empty_mandatory_fields, |
197 |
empty_mandatory_fields => \@empty_mandatory_fields, |
| 178 |
invalid_form_fields => $invalidformfields, |
198 |
invalid_form_fields => $invalidformfields, |
| 179 |
borrower => \%borrower |
199 |
borrower => \%borrower |
| 180 |
); |
200 |
); |
|
|
201 |
$template->param( patron_attribute_classes => GeneratePatronAttributesForm( undef, $attributes ) ); |
| 181 |
|
202 |
|
| 182 |
$template->param( action => 'edit' ); |
203 |
$template->param( action => 'edit' ); |
| 183 |
} |
204 |
} |
|
Lines 215-228
elsif ( $action eq 'update' ) {
Link Here
|
| 215 |
elsif ( $action eq 'edit' ) { #Display logged in borrower's data |
236 |
elsif ( $action eq 'edit' ) { #Display logged in borrower's data |
| 216 |
my $borrower = GetMember( borrowernumber => $borrowernumber ); |
237 |
my $borrower = GetMember( borrowernumber => $borrowernumber ); |
| 217 |
|
238 |
|
| 218 |
if (C4::Context->preference('ExtendedPatronAttributes')) { |
|
|
| 219 |
my $attributes = C4::Members::Attributes::GetBorrowerAttributes($borrowernumber, 'opac'); |
| 220 |
if (scalar(@$attributes) > 0) { |
| 221 |
$borrower->{ExtendedPatronAttributes} = 1; |
| 222 |
$borrower->{patron_attributes} = $attributes; |
| 223 |
} |
| 224 |
} |
| 225 |
|
| 226 |
$template->param( |
239 |
$template->param( |
| 227 |
borrower => $borrower, ); |
240 |
borrower => $borrower, ); |
| 228 |
|
241 |
|
|
Lines 235-240
elsif ( $action eq 'edit' ) { #Display logged in borrower's data
Link Here
|
| 235 |
} |
248 |
} |
| 236 |
} |
249 |
} |
| 237 |
|
250 |
|
|
|
251 |
$template->param( patron_attribute_classes => GeneratePatronAttributesForm( $borrower ) ); |
| 252 |
} else { |
| 253 |
$template->param( patron_attribute_classes => GeneratePatronAttributesForm() ); |
| 238 |
} |
254 |
} |
| 239 |
|
255 |
|
| 240 |
my $captcha = random_string("CCCCC"); |
256 |
my $captcha = random_string("CCCCC"); |
|
Lines 361-363
sub DelEmptyFields {
Link Here
|
| 361 |
|
377 |
|
| 362 |
return %borrower; |
378 |
return %borrower; |
| 363 |
} |
379 |
} |
| 364 |
- |
380 |
|
|
|
381 |
sub GeneratePatronAttributesForm { |
| 382 |
my ( $borrower, $entered_attributes ) = @_; |
| 383 |
|
| 384 |
use Data::Dumper; warn Dumper( $entered_attributes ); |
| 385 |
|
| 386 |
# Get all attribute types and the values for this patron (if applicable) |
| 387 |
my @types = C4::Members::AttributeTypes::GetAttributeTypes(); |
| 388 |
|
| 389 |
if (scalar(@types) == 0) { |
| 390 |
return []; |
| 391 |
} |
| 392 |
|
| 393 |
my %attr_values = (); |
| 394 |
|
| 395 |
if ( $borrower ) { |
| 396 |
my $attributes = C4::Members::Attributes::GetBorrowerAttributes($borrowernumber); |
| 397 |
|
| 398 |
# Remap the patron's attributes into a hash of arrayrefs per attribute (depends on |
| 399 |
# autovivification) |
| 400 |
foreach my $attr (@$attributes) { |
| 401 |
push @{ $attr_values{ $attr->{code} } }, $attr; |
| 402 |
} |
| 403 |
} |
| 404 |
|
| 405 |
if ( $entered_attributes ) { |
| 406 |
foreach my $attr (@$entered_attributes) { |
| 407 |
push @{ $attr_values{ $attr->{code} } }, $attr; |
| 408 |
} |
| 409 |
} |
| 410 |
|
| 411 |
# Find all existing classes |
| 412 |
my @classes = uniq( map { $_->{class} } @types ); |
| 413 |
@classes = sort @classes; |
| 414 |
my %items_by_class; |
| 415 |
|
| 416 |
foreach my $attr_type_desc (@types) { |
| 417 |
my $attr_type = C4::Members::AttributeTypes->fetch( $attr_type_desc->{code} ); |
| 418 |
# Make sure this attribute should be displayed in the OPAC |
| 419 |
next unless ( $attr_type->opac_display() ); |
| 420 |
# Then, make sure it either has values or is editable |
| 421 |
next unless ( $attr_values{ $attr_type->code() } || $attr_type->opac_editable() ); |
| 422 |
|
| 423 |
push @{ $items_by_class{ $attr_type->class() } }, { |
| 424 |
type => $attr_type, |
| 425 |
# If editable, make sure there's at least one empty entry, to make the template's job easier |
| 426 |
values => $attr_values{ $attr_type->code() } || [{}] |
| 427 |
}; |
| 428 |
} |
| 429 |
|
| 430 |
use Data::Dumper; warn Dumper( \%items_by_class ); |
| 431 |
|
| 432 |
# Finally, build a list of containing classes |
| 433 |
my @class_loop; |
| 434 |
foreach my $class (@classes) { |
| 435 |
next unless ( $items_by_class{$class} ); |
| 436 |
|
| 437 |
my $lib = GetAuthorisedValueByCode( 'PA_CLASS', $class, 1 ) || $class; |
| 438 |
push @class_loop, { |
| 439 |
class => $class, |
| 440 |
items => $items_by_class{$class}, |
| 441 |
lib => $lib, |
| 442 |
}; |
| 443 |
} |
| 444 |
|
| 445 |
return \@class_loop; |
| 446 |
} |
| 447 |
|
| 448 |
sub ParsePatronAttributes { |
| 449 |
my ( $cgi ) = @_; |
| 450 |
|
| 451 |
my @codes = $cgi->param('patron_attribute_code'); |
| 452 |
my @values = $cgi->param('patron_attribute_value'); |
| 453 |
my @passwords = $cgi->param('patron_attribute_password'); |
| 454 |
|
| 455 |
my $ea = each_array( @codes, @values, @passwords ); |
| 456 |
my @attributes; |
| 457 |
my %dups = (); |
| 458 |
|
| 459 |
while ( my ( $code, $value, $password ) = $ea->() ) { |
| 460 |
next unless defined($value) and $value ne ''; |
| 461 |
next if exists $dups{$code}->{$value}; |
| 462 |
$dups{$code}->{$value} = 1; |
| 463 |
|
| 464 |
push @attributes, { code => $code, value => $value, password => $password }; |
| 465 |
} |
| 466 |
|
| 467 |
return \@attributes; |
| 468 |
} |