Bug 17301 - Add callnumber to label-edit-batch.pl
[koha.git] / opac / opac-memberentry.pl
blob3fd4c1f1e03c3b35e80191e4db012c9940e12b73
1 #!/usr/bin/perl
3 # This file is part of Koha.
5 # Koha is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
10 # Koha is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with Koha; if not, see <http://www.gnu.org/licenses>.
18 use Modern::Perl;
20 use CGI qw ( -utf8 );
21 use Digest::MD5 qw( md5_base64 md5_hex );
22 use String::Random qw( random_string );
23 use HTML::Entities;
25 use C4::Auth;
26 use C4::Output;
27 use C4::Members;
28 use C4::Form::MessagingPreferences;
29 use Koha::Patrons;
30 use Koha::Patron::Modification;
31 use Koha::Patron::Modifications;
32 use C4::Scrubber;
33 use Email::Valid;
34 use Koha::DateUtils;
35 use Koha::Libraries;
36 use Koha::Patron::Images;
37 use Koha::Token;
39 my $cgi = new CGI;
40 my $dbh = C4::Context->dbh;
42 my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
44 template_name => "opac-memberentry.tt",
45 type => "opac",
46 query => $cgi,
47 authnotrequired => 1,
51 unless ( C4::Context->preference('PatronSelfRegistration') || $borrowernumber )
53 print $cgi->redirect("/cgi-bin/koha/opac-main.pl");
54 exit;
57 my $action = $cgi->param('action') || q{};
58 if ( $action eq q{} ) {
59 if ($borrowernumber) {
60 $action = 'edit';
62 else {
63 $action = 'new';
67 my $mandatory = GetMandatoryFields($action);
69 my @libraries = Koha::Libraries->search;
70 if ( my @libraries_to_display = split '\|', C4::Context->preference('PatronSelfRegistrationLibraryList') ) {
71 @libraries = map { my $b = $_; my $branchcode = $_->branchcode; grep( /^$branchcode$/, @libraries_to_display ) ? $b : () } @libraries;
73 my ( $min, $max ) = C4::Members::get_cardnumber_length();
74 if ( defined $min ) {
75 $template->param(
76 minlength_cardnumber => $min,
77 maxlength_cardnumber => $max
81 $template->param(
82 action => $action,
83 hidden => GetHiddenFields( $mandatory, 'registration' ),
84 mandatory => $mandatory,
85 libraries => \@libraries,
86 OPACPatronDetails => C4::Context->preference('OPACPatronDetails'),
89 if ( $action eq 'create' ) {
91 my %borrower = ParseCgiForBorrower($cgi);
93 %borrower = DelEmptyFields(%borrower);
95 my @empty_mandatory_fields = CheckMandatoryFields( \%borrower, $action );
96 my $invalidformfields = CheckForInvalidFields(\%borrower);
97 delete $borrower{'password2'};
98 my $cardnumber_error_code;
99 if ( !grep { $_ eq 'cardnumber' } @empty_mandatory_fields ) {
100 # No point in checking the cardnumber if it's missing and mandatory, it'll just generate a
101 # spurious length warning.
102 $cardnumber_error_code = checkcardnumber( $borrower{cardnumber}, $borrower{borrowernumber} );
105 if ( @empty_mandatory_fields || @$invalidformfields || $cardnumber_error_code ) {
106 if ( $cardnumber_error_code == 1 ) {
107 $template->param( cardnumber_already_exists => 1 );
108 } elsif ( $cardnumber_error_code == 2 ) {
109 $template->param( cardnumber_wrong_length => 1 );
112 $template->param(
113 empty_mandatory_fields => \@empty_mandatory_fields,
114 invalid_form_fields => $invalidformfields,
115 borrower => \%borrower
118 elsif (
119 md5_base64( uc( $cgi->param('captcha') ) ) ne $cgi->param('captcha_digest') )
121 $template->param(
122 failed_captcha => 1,
123 borrower => \%borrower
126 else {
127 if (
128 C4::Context->boolean_preference(
129 'PatronSelfRegistrationVerifyByEmail')
132 ( $template, $borrowernumber, $cookie ) = get_template_and_user(
134 template_name => "opac-registration-email-sent.tt",
135 type => "opac",
136 query => $cgi,
137 authnotrequired => 1,
140 $template->param( 'email' => $borrower{'email'} );
142 my $verification_token = md5_hex( \%borrower );
144 $borrower{password} = random_string("..........");
145 $borrower{verification_token} = $verification_token;
147 Koha::Patron::Modification->new( \%borrower )->store();
149 #Send verification email
150 my $letter = C4::Letters::GetPreparedLetter(
151 module => 'members',
152 letter_code => 'OPAC_REG_VERIFY',
153 tables => {
154 borrower_modifications => $verification_token,
158 C4::Letters::EnqueueLetter(
160 letter => $letter,
161 message_transport_type => 'email',
162 to_address => $borrower{'email'},
163 from_address =>
164 C4::Context->preference('KohaAdminEmailAddress'),
168 else {
169 ( $template, $borrowernumber, $cookie ) = get_template_and_user(
171 template_name => "opac-registration-confirmation.tt",
172 type => "opac",
173 query => $cgi,
174 authnotrequired => 1,
178 $template->param( OpacPasswordChange =>
179 C4::Context->preference('OpacPasswordChange') );
181 my ( $borrowernumber, $password ) = AddMember_Opac(%borrower);
182 C4::Form::MessagingPreferences::handle_form_action($cgi, { borrowernumber => $borrowernumber }, $template, 1, C4::Context->preference('PatronSelfRegistrationDefaultCategory') ) if $borrowernumber && C4::Context->preference('EnhancedMessagingPreferences');
184 $template->param( password_cleartext => $password );
185 $template->param(
186 borrower => GetMember( borrowernumber => $borrowernumber ) );
187 $template->param(
188 PatronSelfRegistrationAdditionalInstructions =>
189 C4::Context->preference(
190 'PatronSelfRegistrationAdditionalInstructions')
195 elsif ( $action eq 'update' ) {
197 my $borrower = GetMember( borrowernumber => $borrowernumber );
198 die "Wrong CSRF token"
199 unless Koha::Token->new->check_csrf({
200 id => $borrower->{userid},
201 secret => md5_base64( C4::Context->config('pass') ),
202 token => scalar $cgi->param('csrf_token'),
205 my %borrower = ParseCgiForBorrower($cgi);
207 my %borrower_changes = DelEmptyFields(%borrower);
208 my @empty_mandatory_fields =
209 CheckMandatoryFields( \%borrower_changes, $action );
210 my $invalidformfields = CheckForInvalidFields(\%borrower);
212 # Send back the data to the template
213 %borrower = ( %$borrower, %borrower );
215 if (@empty_mandatory_fields || @$invalidformfields) {
216 $template->param(
217 empty_mandatory_fields => \@empty_mandatory_fields,
218 invalid_form_fields => $invalidformfields,
219 borrower => \%borrower,
220 csrf_token => Koha::Token->new->generate_csrf({
221 id => $borrower->{userid},
222 secret => md5_base64( C4::Context->config('pass') ),
226 $template->param( action => 'edit' );
228 else {
229 my %borrower_changes = DelUnchangedFields( $borrowernumber, %borrower );
230 if (%borrower_changes) {
231 ( $template, $borrowernumber, $cookie ) = get_template_and_user(
233 template_name => "opac-memberentry-update-submitted.tt",
234 type => "opac",
235 query => $cgi,
236 authnotrequired => 1,
240 $borrower_changes{borrowernumber} = $borrowernumber;
242 # FIXME update the following with
243 # Koha::Patron::Modifications->search({ borrowernumber => $borrowernumber })->delete;
244 # when bug 17091 will be pushed
245 my $patron_modifications = Koha::Patron::Modifications->search({ borrowernumber => $borrowernumber });
246 while ( my $patron_modification = $patron_modifications->next ) {
247 $patron_modification->delete;
250 my $m = Koha::Patron::Modification->new( \%borrower_changes )->store();
252 $template->param(
253 borrower => GetMember( borrowernumber => $borrowernumber ),
256 else {
257 $template->param(
258 action => 'edit',
259 nochanges => 1,
260 borrower => GetMember( borrowernumber => $borrowernumber ),
261 csrf_token => Koha::Token->new->generate_csrf({
262 id => $borrower->{userid},
263 secret => md5_base64( C4::Context->config('pass') ),
269 elsif ( $action eq 'edit' ) { #Display logged in borrower's data
270 my $borrower = GetMember( borrowernumber => $borrowernumber );
272 if (C4::Context->preference('ExtendedPatronAttributes')) {
273 my $attributes = C4::Members::Attributes::GetBorrowerAttributes($borrowernumber, 'opac');
274 if (scalar(@$attributes) > 0) {
275 $borrower->{ExtendedPatronAttributes} = 1;
276 $borrower->{patron_attributes} = $attributes;
280 $template->param(
281 borrower => $borrower,
282 guarantor => scalar Koha::Patrons->find($borrowernumber)->guarantor(),
283 hidden => GetHiddenFields( $mandatory, 'modification' ),
284 csrf_token => Koha::Token->new->generate_csrf({
285 id => $borrower->{userid},
286 secret => md5_base64( C4::Context->config('pass') ),
290 if (C4::Context->preference('OPACpatronimages')) {
291 my $patron_image = Koha::Patron::Images->find($borrower->{borrowernumber});
292 $template->param( display_patron_image => 1 ) if $patron_image;
297 my $captcha = random_string("CCCCC");
299 $template->param(
300 captcha => $captcha,
301 captcha_digest => md5_base64($captcha)
304 output_html_with_http_headers $cgi, $cookie, $template->output, undef, { force_no_caching => 1 };
306 sub GetHiddenFields {
307 my ( $mandatory, $action ) = @_;
308 my %hidden_fields;
310 my $BorrowerUnwantedField = $action eq 'modification' ?
311 C4::Context->preference( "PatronSelfModificationBorrowerUnwantedField" ) :
312 C4::Context->preference( "PatronSelfRegistrationBorrowerUnwantedField" );
314 my @fields = split( /\|/, $BorrowerUnwantedField || q|| );
315 foreach (@fields) {
316 next unless m/\w/o;
317 #Don't hide mandatory fields
318 next if $mandatory->{$_};
319 $hidden_fields{$_} = 1;
322 return \%hidden_fields;
325 sub GetMandatoryFields {
326 my ($action) = @_;
328 my %mandatory_fields;
330 my $BorrowerMandatoryField =
331 C4::Context->preference("PatronSelfRegistrationBorrowerMandatoryField");
333 my @fields = split( /\|/, $BorrowerMandatoryField );
335 foreach (@fields) {
336 $mandatory_fields{$_} = 1;
339 if ( $action eq 'create' || $action eq 'new' ) {
340 $mandatory_fields{'email'} = 1
341 if C4::Context->boolean_preference(
342 'PatronSelfRegistrationVerifyByEmail');
345 return \%mandatory_fields;
348 sub CheckMandatoryFields {
349 my ( $borrower, $action ) = @_;
351 my @empty_mandatory_fields;
353 my $mandatory_fields = GetMandatoryFields($action);
354 delete $mandatory_fields->{'cardnumber'};
356 foreach my $key ( keys %$mandatory_fields ) {
357 push( @empty_mandatory_fields, $key )
358 unless ( defined( $borrower->{$key} ) && $borrower->{$key} );
361 return @empty_mandatory_fields;
364 sub CheckForInvalidFields {
365 my $minpw = C4::Context->preference('minPasswordLength');
366 my $borrower = shift;
367 my @invalidFields;
368 if ($borrower->{'email'}) {
369 unless ( Email::Valid->address($borrower->{'email'}) ) {
370 push(@invalidFields, "email");
371 } elsif ( C4::Context->preference("PatronSelfRegistrationEmailMustBeUnique") ) {
372 my $patrons_with_same_email = Koha::Patrons->search( { email => $borrower->{email} })->count;
373 if ( $patrons_with_same_email ) {
374 push @invalidFields, "duplicate_email";
378 if ($borrower->{'emailpro'}) {
379 push(@invalidFields, "emailpro") if (!Email::Valid->address($borrower->{'emailpro'}));
381 if ($borrower->{'B_email'}) {
382 push(@invalidFields, "B_email") if (!Email::Valid->address($borrower->{'B_email'}));
384 if ( $borrower->{'password'} ne $borrower->{'password2'} ){
385 push(@invalidFields, "password_match");
387 if ( $borrower->{'password'} && $minpw && (length($borrower->{'password'}) < $minpw) ) {
388 push(@invalidFields, "password_invalid");
390 if ( $borrower->{'password'} ) {
391 push(@invalidFields, "password_spaces") if ($borrower->{'password'} =~ /^\s/ or $borrower->{'password'} =~ /\s$/);
394 return \@invalidFields;
397 sub ParseCgiForBorrower {
398 my ($cgi) = @_;
400 my $scrubber = C4::Scrubber->new();
401 my %borrower;
403 foreach ( $cgi->param ) {
404 if ( $_ =~ '^borrower_' ) {
405 my ($key) = substr( $_, 9 );
406 $borrower{$key} = HTML::Entities::encode( $scrubber->scrub( scalar $cgi->param($_) ) );
410 my $dob_dt;
411 $dob_dt = eval { dt_from_string( $borrower{'dateofbirth'} ); }
412 if ( $borrower{'dateofbirth'} );
414 if ( $dob_dt ) {
415 $borrower{'dateofbirth'} = output_pref ( { dt => $dob_dt, dateonly => 1, dateformat => 'iso' } );
417 else {
418 # Trigger validation
419 $borrower{'dateofbirth'} = undef;
422 return %borrower;
425 sub DelUnchangedFields {
426 my ( $borrowernumber, %new_data ) = @_;
428 my $current_data = GetMember( borrowernumber => $borrowernumber );
430 foreach my $key ( keys %new_data ) {
431 if ( $current_data->{$key} eq $new_data{$key} ) {
432 delete $new_data{$key};
436 return %new_data;
439 sub DelEmptyFields {
440 my (%borrower) = @_;
442 foreach my $key ( keys %borrower ) {
443 delete $borrower{$key} unless $borrower{$key};
446 return %borrower;