|
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 85-90
$template->param(
Link Here
|
| 85 |
OPACPatronDetails => C4::Context->preference('OPACPatronDetails'), |
87 |
OPACPatronDetails => C4::Context->preference('OPACPatronDetails'), |
| 86 |
); |
88 |
); |
| 87 |
|
89 |
|
|
|
90 |
my $attributes = ParsePatronAttributes($cgi); |
| 91 |
my $conflicting_attribute = 0; |
| 92 |
|
| 93 |
foreach my $attr (@$attributes) { |
| 94 |
unless ( C4::Members::Attributes::CheckUniqueness($attr->{code}, $attr->{value}, $borrowernumber) ) { |
| 95 |
my $attr_info = C4::Members::AttributeTypes->fetch($attr->{code}); |
| 96 |
$template->param( |
| 97 |
extended_unique_id_failed_code => $attr->{code}, |
| 98 |
extended_unique_id_failed_value => $attr->{value}, |
| 99 |
extended_unique_id_failed_description => $attr_info->description() |
| 100 |
); |
| 101 |
$conflicting_attribute = 1; |
| 102 |
} |
| 103 |
} |
| 104 |
|
| 88 |
if ( $action eq 'create' ) { |
105 |
if ( $action eq 'create' ) { |
| 89 |
|
106 |
|
| 90 |
my %borrower = ParseCgiForBorrower($cgi); |
107 |
my %borrower = ParseCgiForBorrower($cgi); |
|
Lines 101-107
if ( $action eq 'create' ) {
Link Here
|
| 101 |
$cardnumber_error_code = checkcardnumber( $borrower{cardnumber}, $borrower{borrowernumber} ); |
118 |
$cardnumber_error_code = checkcardnumber( $borrower{cardnumber}, $borrower{borrowernumber} ); |
| 102 |
} |
119 |
} |
| 103 |
|
120 |
|
| 104 |
if ( @empty_mandatory_fields || @$invalidformfields || $cardnumber_error_code ) { |
121 |
if ( @empty_mandatory_fields || @$invalidformfields || $cardnumber_error_code || $conflicting_attribute ) { |
| 105 |
if ( $cardnumber_error_code == 1 ) { |
122 |
if ( $cardnumber_error_code == 1 ) { |
| 106 |
$template->param( cardnumber_already_exists => 1 ); |
123 |
$template->param( cardnumber_already_exists => 1 ); |
| 107 |
} elsif ( $cardnumber_error_code == 2 ) { |
124 |
} elsif ( $cardnumber_error_code == 2 ) { |
|
Lines 113-118
if ( $action eq 'create' ) {
Link Here
|
| 113 |
invalid_form_fields => $invalidformfields, |
130 |
invalid_form_fields => $invalidformfields, |
| 114 |
borrower => \%borrower |
131 |
borrower => \%borrower |
| 115 |
); |
132 |
); |
|
|
133 |
$template->param( patron_attribute_classes => GeneratePatronAttributesForm( undef, $attributes ) ); |
| 116 |
} |
134 |
} |
| 117 |
elsif ( |
135 |
elsif ( |
| 118 |
md5_base64( uc( $cgi->param('captcha') ) ) ne $cgi->param('captcha_digest') ) |
136 |
md5_base64( uc( $cgi->param('captcha') ) ) ne $cgi->param('captcha_digest') ) |
|
Lines 121-126
if ( $action eq 'create' ) {
Link Here
|
| 121 |
failed_captcha => 1, |
139 |
failed_captcha => 1, |
| 122 |
borrower => \%borrower |
140 |
borrower => \%borrower |
| 123 |
); |
141 |
); |
|
|
142 |
$template->param( patron_attribute_classes => GeneratePatronAttributesForm( undef, $attributes ) ); |
| 124 |
} |
143 |
} |
| 125 |
else { |
144 |
else { |
| 126 |
if ( |
145 |
if ( |
|
Lines 178-183
if ( $action eq 'create' ) {
Link Here
|
| 178 |
C4::Context->preference('OpacPasswordChange') ); |
197 |
C4::Context->preference('OpacPasswordChange') ); |
| 179 |
|
198 |
|
| 180 |
my ( $borrowernumber, $password ) = AddMember_Opac(%borrower); |
199 |
my ( $borrowernumber, $password ) = AddMember_Opac(%borrower); |
|
|
200 |
C4::Members::Attributes::SetBorrowerAttributes( $borrowernumber, $attributes ); |
| 181 |
C4::Form::MessagingPreferences::handle_form_action($cgi, { borrowernumber => $borrowernumber }, $template, 1, C4::Context->preference('PatronSelfRegistrationDefaultCategory') ) if $borrowernumber && C4::Context->preference('EnhancedMessagingPreferences'); |
201 |
C4::Form::MessagingPreferences::handle_form_action($cgi, { borrowernumber => $borrowernumber }, $template, 1, C4::Context->preference('PatronSelfRegistrationDefaultCategory') ) if $borrowernumber && C4::Context->preference('EnhancedMessagingPreferences'); |
| 182 |
|
202 |
|
| 183 |
$template->param( password_cleartext => $password ); |
203 |
$template->param( password_cleartext => $password ); |
|
Lines 221-226
elsif ( $action eq 'update' ) {
Link Here
|
| 221 |
secret => md5_base64( C4::Context->config('pass') ), |
241 |
secret => md5_base64( C4::Context->config('pass') ), |
| 222 |
}), |
242 |
}), |
| 223 |
); |
243 |
); |
|
|
244 |
$template->param( patron_attribute_classes => GeneratePatronAttributesForm( undef, $attributes ) ); |
| 224 |
|
245 |
|
| 225 |
$template->param( action => 'edit' ); |
246 |
$template->param( action => 'edit' ); |
| 226 |
} |
247 |
} |
|
Lines 268-281
elsif ( $action eq 'update' ) {
Link Here
|
| 268 |
elsif ( $action eq 'edit' ) { #Display logged in borrower's data |
289 |
elsif ( $action eq 'edit' ) { #Display logged in borrower's data |
| 269 |
my $borrower = GetMember( borrowernumber => $borrowernumber ); |
290 |
my $borrower = GetMember( borrowernumber => $borrowernumber ); |
| 270 |
|
291 |
|
| 271 |
if (C4::Context->preference('ExtendedPatronAttributes')) { |
|
|
| 272 |
my $attributes = C4::Members::Attributes::GetBorrowerAttributes($borrowernumber, 'opac'); |
| 273 |
if (scalar(@$attributes) > 0) { |
| 274 |
$borrower->{ExtendedPatronAttributes} = 1; |
| 275 |
$borrower->{patron_attributes} = $attributes; |
| 276 |
} |
| 277 |
} |
| 278 |
|
| 279 |
$template->param( |
292 |
$template->param( |
| 280 |
borrower => $borrower, |
293 |
borrower => $borrower, |
| 281 |
guarantor => scalar Koha::Patrons->find($borrowernumber)->guarantor(), |
294 |
guarantor => scalar Koha::Patrons->find($borrowernumber)->guarantor(), |
|
Lines 291-296
elsif ( $action eq 'edit' ) { #Display logged in borrower's data
Link Here
|
| 291 |
$template->param( display_patron_image => 1 ) if $patron_image; |
304 |
$template->param( display_patron_image => 1 ) if $patron_image; |
| 292 |
} |
305 |
} |
| 293 |
|
306 |
|
|
|
307 |
$template->param( patron_attribute_classes => GeneratePatronAttributesForm( $borrower ) ); |
| 308 |
} else { |
| 309 |
$template->param( patron_attribute_classes => GeneratePatronAttributesForm() ); |
| 294 |
} |
310 |
} |
| 295 |
|
311 |
|
| 296 |
my $captcha = random_string("CCCCC"); |
312 |
my $captcha = random_string("CCCCC"); |
|
Lines 444-446
sub DelEmptyFields {
Link Here
|
| 444 |
|
460 |
|
| 445 |
return %borrower; |
461 |
return %borrower; |
| 446 |
} |
462 |
} |
| 447 |
- |
463 |
|
|
|
464 |
sub GeneratePatronAttributesForm { |
| 465 |
my ( $borrower, $entered_attributes ) = @_; |
| 466 |
|
| 467 |
use Data::Dumper; warn Dumper( $entered_attributes ); |
| 468 |
|
| 469 |
# Get all attribute types and the values for this patron (if applicable) |
| 470 |
my @types = C4::Members::AttributeTypes::GetAttributeTypes(); |
| 471 |
|
| 472 |
if (scalar(@types) == 0) { |
| 473 |
return []; |
| 474 |
} |
| 475 |
|
| 476 |
my %attr_values = (); |
| 477 |
|
| 478 |
if ( $borrower ) { |
| 479 |
my $attributes = C4::Members::Attributes::GetBorrowerAttributes($borrowernumber); |
| 480 |
|
| 481 |
# Remap the patron's attributes into a hash of arrayrefs per attribute (depends on |
| 482 |
# autovivification) |
| 483 |
foreach my $attr (@$attributes) { |
| 484 |
push @{ $attr_values{ $attr->{code} } }, $attr; |
| 485 |
} |
| 486 |
} |
| 487 |
|
| 488 |
if ( $entered_attributes ) { |
| 489 |
foreach my $attr (@$entered_attributes) { |
| 490 |
push @{ $attr_values{ $attr->{code} } }, $attr; |
| 491 |
} |
| 492 |
} |
| 493 |
|
| 494 |
# Find all existing classes |
| 495 |
my @classes = uniq( map { $_->{class} } @types ); |
| 496 |
@classes = sort @classes; |
| 497 |
my %items_by_class; |
| 498 |
|
| 499 |
foreach my $attr_type_desc (@types) { |
| 500 |
my $attr_type = C4::Members::AttributeTypes->fetch( $attr_type_desc->{code} ); |
| 501 |
# Make sure this attribute should be displayed in the OPAC |
| 502 |
next unless ( $attr_type->opac_display() ); |
| 503 |
# Then, make sure it either has values or is editable |
| 504 |
next unless ( $attr_values{ $attr_type->code() } || $attr_type->opac_editable() ); |
| 505 |
|
| 506 |
push @{ $items_by_class{ $attr_type->class() } }, { |
| 507 |
type => $attr_type, |
| 508 |
# If editable, make sure there's at least one empty entry, to make the template's job easier |
| 509 |
values => $attr_values{ $attr_type->code() } || [{}] |
| 510 |
}; |
| 511 |
} |
| 512 |
|
| 513 |
use Data::Dumper; warn Dumper( \%items_by_class ); |
| 514 |
|
| 515 |
# Finally, build a list of containing classes |
| 516 |
my @class_loop; |
| 517 |
foreach my $class (@classes) { |
| 518 |
next unless ( $items_by_class{$class} ); |
| 519 |
|
| 520 |
my $lib = GetAuthorisedValueByCode( 'PA_CLASS', $class, 1 ) || $class; |
| 521 |
push @class_loop, { |
| 522 |
class => $class, |
| 523 |
items => $items_by_class{$class}, |
| 524 |
lib => $lib, |
| 525 |
}; |
| 526 |
} |
| 527 |
|
| 528 |
return \@class_loop; |
| 529 |
} |
| 530 |
|
| 531 |
sub ParsePatronAttributes { |
| 532 |
my ( $cgi ) = @_; |
| 533 |
|
| 534 |
my @codes = $cgi->param('patron_attribute_code'); |
| 535 |
my @values = $cgi->param('patron_attribute_value'); |
| 536 |
my @passwords = $cgi->param('patron_attribute_password'); |
| 537 |
|
| 538 |
my $ea = each_array( @codes, @values, @passwords ); |
| 539 |
my @attributes; |
| 540 |
my %dups = (); |
| 541 |
|
| 542 |
while ( my ( $code, $value, $password ) = $ea->() ) { |
| 543 |
next unless defined($value) and $value ne ''; |
| 544 |
next if exists $dups{$code}->{$value}; |
| 545 |
$dups{$code}->{$value} = 1; |
| 546 |
|
| 547 |
push @attributes, { code => $code, value => $value, password => $password }; |
| 548 |
} |
| 549 |
|
| 550 |
return \@attributes; |
| 551 |
} |