use OpenSRF::Utils::Logger qw/$logger/;
use OpenILS::Utils::Fieldmapper;
use OpenILS::Application::AppUtils;
+use OpenILS::Utils::CStoreEditor qw/:funcs/;
use OpenILS::Event;
use Data::Dumper;
$Data::Dumper::Indent = 0;
my $ctx = $self->ctx;
my $cgi = $self->cgi;
$ctx->{register} = {};
+ $self->collect_register_validation_settings;
# just loading the form
return Apache2::Const::OK
# user
foreach (grep /^stgu\./, $cgi->param) {
my $val = $cgi->param($_);
- # TODO validate
+ $self->inspect_register_value($_, $val);
s/^stgu\.//g;
$user->$_($val);
}
# address
foreach (grep /^stgma\./, $cgi->param) {
my $val = $cgi->param($_);
- # TODO validate
+ $self->inspect_register_value($_, $val);
s/^stgma\.//g;
$addr->$_($val);
}
+ # At least one value was invalid. Exit early and re-render.
+ return Apache2::Const::OK if $ctx->{register}{invalid};
+
# user.stage.create will generate a temporary usrname and
# link the user and address objects via this username in the DB.
my $resp = $U->simplereq(
return Apache2::Const::OK;
}
+
+sub collect_register_validation_settings {
+ my $self = shift;
+ my $ctx = $self->ctx;
+ my $e = new_editor();
+ my $ctx_org = $ctx->{physical_loc} || $self->_get_search_lib;
+ my $shash = $self->{register}{settings} = {};
+
+ # retrieve the org unit setting types and values
+ # that are relevant to our validation tasks.
+
+ my $settings = $e->json_query({
+ select => {coust => ['name']},
+ from => 'coust',
+ where => {name => {like => 'ui.patron.edit.%.%.%'}}
+ });
+
+ # load org setting values for all of the regex,
+ # example, show, and require settings
+ for my $set (@$settings) {
+ $set = $set->{name};
+ next unless $set =~ /regex$|show$|require$|example$/;
+
+ my $val = $ctx->{get_org_setting}->($ctx_org, $set);
+ next unless $val; # no configured org setting
+
+ # extract the field class, name, and
+ # setting type from the setting name
+ my (undef, undef, undef, $cls, $field, $type) = split(/\./, $set);
+
+ # translate classes into stage classes
+ my $scls = ($cls eq 'au') ? 'stgu' : 'stgma';
+
+ $shash->{$scls}{$field}{$type} = $val;
+ }
+
+ # use the generic phone settings where none are provided for day_phone.
+
+ $shash->{stgu}{day_phone}{example} =
+ $ctx->{get_org_setting}->($ctx_org, 'ui.patron.edit.phone.example')
+ unless $shash->{stgu}{day_phone}{example};
+
+ $shash->{stgu}{day_phone}{regex} =
+ $ctx->{get_org_setting}->($ctx_org, 'ui.patron.edit.phone.regex')
+ unless $shash->{stgu}{day_phone}{regex};
+
+ # some fields are assumed to be visible / required even without the
+ # presence of org unit settings. E.g. we obviously want the user to
+ # enter a name, since a name is required for ultimately creating a user
+ # account. We can mimic that by forcing some org unit setting values
+
+ $shash->{stgu}{first_given_name}{require} = 1
+ unless defined $shash->{stgu}{first_given_name}{require};
+ $shash->{stgu}{second_given_name}{show} = 1
+ unless defined $shash->{stgu}{second_given_name}{show};
+ $shash->{stgu}{family_name}{require} = 1
+ unless defined $shash->{stgu}{family_name}{require};
+ $shash->{stgma}{street1}{require} = 1
+ unless defined $shash->{stgma}{street1}{require};
+ $shash->{stgma}{city}{require} = 1
+ unless defined $shash->{stgma}{city}{require};
+ $shash->{stgma}{post_code}{require} = 1
+ unless defined $shash->{stgma}{post_code}{require};
+
+ $ctx->{register}{settings} = $shash;
+}
+
+# inspects each value and determines, based on org unit settings,
+# if the value is invalid. Invalid is defined as not providing
+# a value when one is required or not matching the configured regex.
+sub inspect_register_value {
+ my ($self, $field_path, $value) = @_;
+ my $ctx = $self->ctx;
+ my ($scls, $field) = split(/\./, $field_path);
+
+ if (!$value) {
+
+ if ($self->{register}{settings}{$scls}{$field}{require}) {
+ $ctx->{register}{invalid}{$scls}{$field}{require} = 1;
+
+ $logger->info("patron register field $field ".
+ "requires a value, but none was entered");
+ }
+ return;
+ }
+
+ my $regex = $self->{register}{settings}{$scls}{$field}{regex};
+ return if !$regex or $value =~ /$regex/; # field is valid
+
+ $logger->info("invalid value was provided for patron ".
+ "register field=$field; pattern=$regex; value=$value");
+
+ $ctx->{register}{invalid}{$scls}{$field}{regex} = 1;
+
+ return;
+}
+
+
+
PROCESS "opac/parts/org_selector.tt2";
WRAPPER "opac/parts/base.tt2";
INCLUDE "opac/parts/topnav.tt2";
- ctx.page_title = l("Request Library Card") %]
- <div id="content-wrapper">
- <div id="main-content-register">
- <div class="common-full-pad"></div>
- <h1>[% l('Request a Library Card')%]</h1>
- <hr/>
+ ctx.page_title = l("Request Library Card");
- [% IF ctx.register.success %]
- <h3>[% |l %]
- Registration successful! Please see library staff to
- complete your registration.
- [% END %]</h3>
- [% ELSIF ctx.register.error %]
- <h3>[% |l %]
- An registration error has occurred. Please see library staff.
- [% END %]</h3>
+# some useful variables and MACROs for display,
+# field validation, and added info display
- [% ELSE;
- ctx_org = ctx.physical_loc || ctx.search_ou || ctx.aou_tree.id ;
+ctx_org = ctx.physical_loc || ctx.search_ou || ctx.aou_tree.id;
- addr_required = ctx.get_org_setting(ctx_org,
- 'ui.patron.registration.require_address');
+# list of the registration fields to (potentially)
+# display in the order they should be shown
- # true if the selected field is required
- MACRO require_field(cls, field_name) BLOCK;
- sname = "ui.patron.edit.${cls}.${field_name}.require";
- IF ctx.get_org_setting(ctx_org, sname); 1; ELSE; 0; END;
- END;
+register_fields = [
+ {class => 'stgu', name = 'first_given_name', label => l('First Name')},
+ {class => 'stgu', name = 'second_given_name', label => l('Middle Name')},
+ {class => 'stgu', name = 'family_name', label => l('Last Name')},
+ {class => 'stgu', name = 'family_name', label => l('Last Name')},
+ {class => 'stgma', name = 'street1', label => l('Street Address')},
+ {class => 'stgma', name = 'street2', label => l('Street Address (2)')},
+ {class => 'stgma', name = 'city', label => l('City')},
+ {class => 'stgma', name = 'county', label => l('County')},
+ {class => 'stgma', name = 'state', label => l('State')},
+ {class => 'stgma', name = 'post_code', label => l('Zip Code')},
+ {class => 'stgu', name = 'dob', label => l('Date of Birth')},
+ {class => 'stgu', name = 'day_phone', label => l('Phone Number')},
+ {class => 'stgu', name = 'email', label => l('Email Address')}
+];
+%]
- # true if the selected field should be shown
- MACRO show_field(cls, field_name) BLOCK;
- sname = "ui.patron.edit.${cls}.${field_name}.show";
- IF require_field(cls, field_name) ||
- ctx.get_org_setting(ctx_org, sname); 1; ELSE; 0; END;
- END;
+<div id="content-wrapper">
+ <div id="main-content-register">
+ <div class="common-full-pad"></div>
+ <h1>[% l('Request a Library Card')%]</h1>
+ <hr/>
- # indicate whether a field is optional; display example text
- MACRO show_field_extras(cls, field_name, test_req, test_ex) BLOCK;
- required = 0;
- example = '';
+ [% IF ctx.register.success %]
+ <h3>[% |l %]
+ Registration successful! Please see library staff to
+ complete your registration.
+ [% END %]</h3>
- sname = "ui.patron.edit.${cls}.${field_name}.example";
- IF test_ex;
- example = ctx.get_org_setting(ctx_org, sname);
+ [% ELSIF ctx.register.error %]
+ <h3>[% |l %]
+ An registration error has occurred. Please see library staff.
+ [% END %]</h3>
- # day_phone is a special case, since there is a both
- # a day_phone example and generic phone example
- IF field_name == 'day_phone' AND !example;
- sname = 'ui.patron.edit.phone.example';
- example = ctx.get_org_setting(ctx_org, sname);
- END;
- END;
-
- SET required = require_field(cls, field_name) IF test_req;
- IF example;
- IF required;
- l('(Example: [_1])', example);
- ELSE;
- l('(Optional, Example: [_1])', example);
- END;
- ELSIF !required;
- l('(Optional)');
- END;
- END;
- %]
+ [% ELSE %]
- <form method='POST'>
- <table>
- <!-- TODO <label>s -->
- <tr>
- <td>[% l('Home Library') %]</td>
- <td>[% INCLUDE build_org_selector
- # TODO: limit to orgs where pending-allowed
- name='stgu.home_ou'
- value=ctx_org
- can_have_users_only=1
- %]
- </td>
- </tr>
- <tr>
- <td>[% l('First Name') %]</td>
- <td><input type='text' name='stgu.first_given_name'/></td>
- </tr>
- <tr>
- <td>[% l('Middle Name') %]</td>
- <td><input type='text' name='stgu.second_given_name'/></td>
- </tr>
- <tr>
- <td>[% l('Last Name') %]</td>
- <td><input type='text' name='stgu.family_name'/></td>
- </tr>
+ <form method='POST'>
+ <table>
+ <!-- TODO <label>s -->
+ <tr>
+ <td>
+ <label for='stgu.home_ou'>[% l('Home Library') %]</label>
+ </td>
+ <td>[% INCLUDE build_org_selector
+ # TODO: limit to orgs where pending-allowed
+ name='stgu.home_ou'
+ value=ctx_org
+ can_have_users_only=1
+ %]
+ </td>
+ </tr>
+[%
+# <=== shifting code left for readability
- [% IF addr_required # --------------------------------- %]
- <tr>
- <td>[% l('Street Address') %]</td>
- <td><input type='text' name='stgma.street1'/></td>
- </tr>
- <tr>
- <td>[% l('Street Address (2)') %]</td>
- <td><input type='text' name='stgma.street2'/></td>
- <td>[% l('(Optional)') %]</td>
- </tr>
- <tr>
- <td>[% l('City') %]</td>
- <td><input type='text' name='stgma.city'/></td>
- </tr>
- [% IF show_field('aua', 'state') %]
- <tr>
- <td>[% l('State') %]</td>
- <td><input type='text' name='stgma.state'/></td>
- <td>[% show_field_extras('aua', 'state', 1) %]</td>
- </tr>
- [% END %]
- <tr>
- <td>[% l('Post/Zip Code') %]</td>
- <td><input type='text' name='stgma.post_code'/></td>
- <td>[% show_field_extras('aua', 'post_code', 0, 1) %]</td>
- </tr>
- [% IF show_field('aua', 'county') %]
- <tr>
- <td>[% l('County') %]</td>
- <td><input type='text' name='stgma.county'/></td>
- <td>[% show_field_extras('aua', 'county', 1) %]</td>
- </tr>
- [% END %]
- [% END # addr_required -------------------------------- %]
+# render the table row for each of the register fields
+FOR field_def IN register_fields;
+ fclass = field_def.class;
+ fname = field_def.name;
+ field_path = fclass _ "." _ fname;
- [% IF show_field('au', 'dob') %]
- <tr>
- <td>[% l('Date of Birth') %]</td>
- <td><input type='text' name='stgu.dob'/></td>
- <td>[% show_field_extras('au', 'dob', 1) %]</td>
- </tr>
- [% END %]
- [% IF show_field('au', 'day_phone') %]
- <tr>
- <td>[% l('Phone Number') %]</td>
- <td><input type='text' name='stgu.day_phone'/></td>
- <td>[% show_field_extras('au', 'day_phone', 1, 1) %]</td>
- </tr>
- [% END %]
- [% IF show_field('au', 'email') %]
- <tr>
- <td>[% l('Email Address') %]</td>
- <td><input type='text' name='stgu.email'/></td>
- <td>[% show_field_extras('au', 'email', 1, 1) %]</td>
- </tr>
- [% END %]
+ show = ctx.register.settings.$fclass.$fname.show;
+ require = ctx.register.settings.$fclass.$fname.require;
+ example = ctx.register.settings.$fclass.$fname.example;
+
+ invalid_require = ctx.register.invalid.$fclass.$fname.require;
+ invalid_regex = ctx.register.invalid.$fclass.$fname.regex;
+
+ NEXT UNLESS require OR show;
+%]
+<tr>
+ <td>
+ <label for='[% field_path %]'>[% field_def.label | html %]</label>
+ </td>
+ <td>
+ <input
+ type='text'
+ name='[% field_path %]'
+ value='[% CGI.param(field_path) | html %]'/>
+ </td>
+ <td>
+[%
+ # display wether the field is optional and any example text
+
+ IF example;
+ IF require;
+ l('(Example: [_1])', example);
+ ELSE;
+ l('(Optional, Example: [_1])', example);
+ END;
+ ELSIF !require;
+ l('(Optional)');
+ END;
+%]
+ </td>
+ <td>
+ [% IF invalid_require %]
+ <span class='patron-reg-invalid'>
+ [% l('This field is required') %]
+ </span>
+ [% ELSIF invalid_regex %]
+ <span class='patron-reg-invalid'>
+ [% l('The provided value does not have the correct format') %]
+ </span>
+ [% END %]
+ </td>
+</tr>
+[% END;
+# ====> shifting the code back to the right for context %]
<tr>
<td>
<a href="[% ctx.opac_root %]/home"
</table>
</form>
[% END %]
-
<div class="common-full-pad"></div>
</div>
</div>