[% IF ( invalid_smsnumber ) %]is not valid and cannot be saved[% ELSE %]is required in order to set SMS preferences[% END %].
[% IF ( settings_updated ) %]
Settings updated
[% END %]
@@ -198,14 +201,30 @@
}
});
+ [% IF ( ValidateEmailAddress ) %]
+ [% IF !BORROWER_INF.email %]
+ disableCheckboxesWithInvalidPreferences($("#email"), "email");
+ [% END %]
+ [% END %]
[% IF ( ValidatePhoneNumber ) %]
- $("#SMSnumber").on("change", function(){
+ [% IF !BORROWER_INF.smsalertnumber %]
+ disableCheckboxesWithInvalidPreferences($("#SMSnumber"), "sms");
+ [% END %]
+ [% IF !BORROWER_INF.phone %]
+ disableCheckboxesWithInvalidPreferences($("#phone"), "phone");
+ [% END %]
+
+ $("#SMSnumber").on("input", function(){
+ disableCheckboxesWithInvalidPreferences($(this), "sms");
+ });
+ $("#SMSnumber").on("change", function(){
$(this).val($.trim($(this).val()));
- });
+ disableCheckboxesWithInvalidPreferences($(this), "sms");
+ });
[% END %]
-
});
//]]>
+
[% END %]
--- a/koha-tmpl/opac-tmpl/bootstrap/js/messaging-preference.js
+++ a/koha-tmpl/opac-tmpl/bootstrap/js/messaging-preference.js
@@ -0,0 +1,91 @@
+/**
+ *
+ * Used in: koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-messaging.tt
+ *
+ * This component is also used in Staff client: koha-tmpl/intranet-tmpl/prog/en/modules/memberentrygen.tt
+ * For modifications, edit also Staff client version in: koha-tmpl/intranet-tmpl/prog/en/js/messaging-preference.js
+ *
+ * Disables and clears checkboxes from messaging preferences
+ * if there is either invalid or nonexistent contact information
+ * for the message transfer type.
+ *
+ * @param {HTMLInputElement} elem
+ * The contact field
+ * @param {string} id_attr
+ * Checkboxes' id attribute so that we can recognize them
+ */
+// Settings for messaging-preference.js
+var patron_messaging_checkbox_preferences = {
+ email: {
+ checked_checkboxes: null,
+ is_enabled: true,
+ disabled_checkboxes: null
+ },
+ sms: {
+ checked_checkboxes: null,
+ is_enabled: true,
+ disabled_checkboxes: null
+ },
+ phone: {
+ checked_checkboxes: null,
+ is_enabled: true,
+ disabled_checkboxes: null
+ }
+};
+
+function disableCheckboxesWithInvalidPreferences(elem, id_attr) {
+ // Get checkbox preferences for the element
+ var checkbox_prefs = eval("patron_messaging_checkbox_preferences." + id_attr);
+ // Check if element is empty or not valid
+
+ if (!$(elem).length || $(elem).val().length == 0 || !$(elem).valid()) {
+
+ if (checkbox_prefs.is_enabled) {
+ // Save the state of checked checkboxes
+ checkbox_prefs.checked_checkboxes = $("input[type='checkbox'][id^=" + id_attr + "][value=" + id_attr + "]:checked");
+
+ // Save the state of automatically disabled checkboxes
+ // (We don't want to enable them once the e-mail is valid!)
+ checkbox_prefs.disabled_checkboxes = $("input[type='checkbox'][id^=" + id_attr + "][value=" + id_attr + "]:disabled");
+
+ // Clear patron messaging preferences checkboxes
+ $("input[type='checkbox'][id^=" + id_attr + "][value=" + id_attr + "]").removeAttr("checked");
+
+ // Then disable checkboxes from patron messaging perferences
+ $("input[type='checkbox'][id^=" + id_attr + "][value=" + id_attr + "]").attr("disabled", "disabled");
+
+ // Color table cell's background emphasize the disabled state of the checkbox
+ $("input[type='checkbox'][id^=" + id_attr + "][value=" + id_attr + "]").parent().css("background-color", "#E8F0F8");
+
+ // Show notice about missing contact in messaging preferences box
+ $("#required-" + id_attr).css("display", "block");
+
+ checkbox_prefs.is_enabled = false;
+ }
+ } else {
+
+ if (!checkbox_prefs.is_enabled) {
+ // Enable patron messaging preferences checkboxes
+ $("input[type='checkbox'][id^=" + id_attr + "][value=" + id_attr + "]").removeAttr("disabled");
+
+ // Disable the checkboxes that were disabled by default
+ checkbox_prefs.disabled_checkboxes.each(function() {
+ $(this).attr("disabled", "disabled");
+ $(this).removeAttr("checked");
+ });
+
+ // Restore the state of checkboxes
+ checkbox_prefs.checked_checkboxes.each(function() {
+ $(this).attr("checked", "checked");
+ });
+
+ // Remove the background color from table cell
+ $("input[type='checkbox'][id^=" + id_attr + "][value=" + id_attr + "]").parent().css("background-color", "#FFF");
+
+ // Remove notice about missing contact from messaging preferences box
+ $("#required-" + id_attr).css("display", "none");
+
+ checkbox_prefs.is_enabled = true;
+ }
+ }
+}
--- a/members/memberentry.pl
+++ a/members/memberentry.pl
@@ -441,7 +441,7 @@ if ((!$nok) and $nodouble and ($op eq 'insert' or $op eq 'save')){
C4::Members::Attributes::SetBorrowerAttributes($borrowernumber, $extended_patron_attributes);
}
if (C4::Context->preference('EnhancedMessagingPreferences') and $input->param('setting_messaging_prefs')) {
- C4::Form::MessagingPreferences::handle_form_action($input, { borrowernumber => $borrowernumber }, $template);
+ C4::Form::MessagingPreferences::handle_form_action($input, \%data, $template);
}
}
print scalar ($destination eq "circ") ?
--- a/misc/maintenance/deleteMisconfiguredMessagingPrefs.pl
+++ a/misc/maintenance/deleteMisconfiguredMessagingPrefs.pl
@@ -0,0 +1,213 @@
+#!/usr/bin/perl
+
+#-----------------------------------
+# Copyright 2015 Vaara-kirjastot
+#
+# This file is part of Koha.
+#
+# Koha is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2 of the License, or (at your option) any later
+# version.
+#
+# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with Koha; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#-----------------------------------
+
+use strict;
+use warnings;
+use C4::Context;
+use DBI;
+use Email::Valid;
+use POSIX qw(strftime);
+use Getopt::Long;
+use C4::Members::Messaging;
+
+my $helptext = "
+This script deletes misconfigured messaging preferences from the Koha database. A preference is
+misconfigured if the user has no valid contact information for that type of transport method.
+E.g user wants messages via e-mail while he has not provided an e-mail address.
+
+Options:
+ -h|--help Prints this help documentation.
+ -b|--backup:s Filename for backup file. Required in 'restore' mode and optional in 'delete' mode.
+ Default value is messaging-prefs-backup_. In 'delete' mode, if nothing
+ gets deleted, the file will not be created.
+ -d|--delete Activates the deletion mode (cannot be used simultaneously with mode 'restore').
+ -r|--restore Activates the restore mode (cannot be used simultaneously with mode 'delete').
+ -m|--methods=s{1,3} Optional. Specifies the transfer methods/types. The three types are: email phone sms.
+ If not provided, all three types are used.
+
+Examples:
+ ./deleteMisconfiguredMessagingPrefs.pl -d -b
+ ./deleteMisconfiguredMessagingPrefs.pl -d -t email phone -b
+ ./deleteMisconfiguredMessagingPrefs.pl -d -t email phone sms -b my_backup_file
+ ./deleteMisconfiguredMessagingPrefs.pl -r -b my_backup_file
+\n";
+
+my ($help, $delete, $filename, $restore, @methods);
+
+GetOptions(
+ 'h|help' => \$help,
+ 'd|delete' => \$delete,
+ 'r|restore' => \$restore,
+ 'b|backup:s' => \$filename,
+ 'm|methods=s{1,3}' => \@methods
+);
+
+my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();
+my $are_we_doing_backups = 0;
+
+
+if ($help || $restore && $delete || !$restore && !$delete) {
+ die $helptext;
+}
+if ($delete and $filename eq "" or length($filename) > 0) {
+ $are_we_doing_backups = 1;
+ $filename = (strftime "messaging-prefs-backup_%Y-%m-%d_%H-%M-%S", localtime) if ($filename eq "");
+}
+
+
+
+
+
+
+
+
+
+
+
+
+if ($delete) {
+ my @deleted_prefs;
+
+ # check if user has specified messaging transport methods
+ if (@methods > 0 && @methods < 4) {
+ my $correct_modes = 0;
+
+ foreach my $type (@methods){
+
+ if ($type eq "email" or $type eq "phone" or $type eq "sms") {
+ print "Deleting misconfigured $type messaging preferences\n";
+
+ # method exists, don't need to print warning anymore
+ $correct_modes = 1;
+
+ # which contact info field (primary email / primary phone / smsalertnumber)
+ # should we check?
+ my $contact;
+ $contact = "email" if $type eq "email";
+ $contact = "phone" if $type eq "phone";
+ $contact = "smsalertnumber" if $type eq "sms";
+
+ # which validator should we use?
+ my $validator;
+ $validator = "email" if $type eq "email";
+ $validator = "phone" if $type eq "phone" or $type eq "sms";
+
+ # delete the misconfigured prefs and keep a counting them
+ push(@deleted_prefs, C4::Members::Messaging::DeleteMisconfiguredPreference($type, $contact, $validator));
+ }
+ }
+
+ die "Missing or invalid in parameter --type values. See help.\n$helptext" if $correct_modes == 0;
+
+ } else {
+
+ # user did not specify any methods. so let's delete them all!
+ print "Deleting all misconfigured messaging preferences\n";
+ push(@deleted_prefs, C4::Members::Messaging::DeleteAllMisconfiguredPreferences());
+
+ }
+
+ BackupDeletedPrefs(@deleted_prefs) if $are_we_doing_backups;
+
+ print "Deleted ".scalar(@deleted_prefs)." misconfigured messaging preferences in total.\n";
+}
+elsif ($restore){
+ if (@methods > 0) {
+ my $correct_modes = 0;
+ for (my $i=0; $i < @methods; $i++){
+ if ($methods[$i] ne "email" and $methods[$i] ne "phone" and $methods[$i] ne "sms") {
+ print "Invalid type $methods[$i]. Valid types are: email phone sms\n";
+ splice(@methods, $i);
+ }
+ }
+ die "Missing parameter --type values. See help.\n$helptext" if @methods == 0;
+ RestoreDeletedPreferences(@methods);
+ } else {
+ RestoreDeletedPreferences();
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# restoring deleted prefs
+
+sub BackupDeletedPrefs {
+ my @deleted = @_;
+
+ open(my $fh, ">>", $filename) or die "Could not open file for writing.\n";
+
+ for (my $i=0; $i < @deleted; $i++){
+ say $fh $deleted[$i][0].",".$deleted[$i][1];
+ }
+}
+sub RestoreDeletedPreferences {
+ my $count = 0;
+ my @methods = @_;
+
+ my $dbh = C4::Context->dbh();
+ open(my $fh, "<", $filename) or die "Could not open file for writing.\n";
+
+ my $query = "INSERT INTO borrower_message_transport_preferences (borrower_message_preference_id, message_transport_type) VALUES (?,?)";
+ my $sth = $dbh->prepare($query);
+
+ # check if user has specified methods (types)
+ if (@methods > 0) {
+ while (my $line = <$fh>) {
+ my @vars = split(',',$line);
+ my @remlinebreak = split('\\n', $vars[1]);
+ my $pref_id = $vars[0];
+ my $type = $remlinebreak[0];
+
+ if (grep(/$type/,@methods)) {
+ $sth->execute($pref_id, $type) or $count--;
+ $count++;
+ }
+ }
+ } else {
+ # simply walk through each line and restore every single line
+ while (my $line = <$fh>) {
+ my @vars = split(',',$line);
+ next if @vars == 0;
+ my @remlinebreak = split('\\n', $vars[1]);
+ next if not defined $remlinebreak[0];
+ my $pref_id = $vars[0];
+ my $type = $remlinebreak[0];
+
+ $sth->execute($pref_id, $type) or $count--;
+ $count++;
+ }
+ }
+
+ print "Restored $count preferences.\n";
+
+}
--- a/opac/opac-messaging.pl
+++ a/opac/opac-messaging.pl
@@ -68,7 +68,7 @@ if ( defined $query->param('modify') && $query->param('modify') eq 'yes' ) {
$borrower = GetMemberDetails( $borrowernumber );
}
- C4::Form::MessagingPreferences::handle_form_action($query, { borrowernumber => $borrowernumber }, $template);
+ C4::Form::MessagingPreferences::handle_form_action($query, $borrower, $template);
}
C4::Form::MessagingPreferences::set_form_values({ borrowernumber => $borrower->{'borrowernumber'} }, $template);
--- a/t/db_dependent/MessagingPreferencesValidation.t
+++ a/t/db_dependent/MessagingPreferencesValidation.t
@@ -0,0 +1,180 @@
+#!/usr/bin/env perl
+
+# Copyright 2015 Open Source Freedom Fighters
+#
+# This file is part of Koha.
+#
+# Koha is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# Koha is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Koha; if not, see .
+$ENV{KOHA_PAGEOBJECT_DEBUG} = 1;
+use Modern::Perl;
+
+use Test::More;
+use Try::Tiny; #Even Selenium::Remote::Driver uses Try::Tiny :)
+
+use Koha::Auth::PermissionManager;
+
+use t::lib::Page::Mainpage;
+use t::lib::Page::Opac::OpacMain;
+use t::lib::Page::Opac::OpacMemberentry;
+use t::lib::Page::Members::Memberentry;
+use t::lib::Page::Members::Moremember;
+
+use t::lib::TestObjects::BorrowerFactory;
+use t::lib::TestObjects::SystemPreferenceFactory;
+
+##Setting up the test context
+my $testContext = {};
+
+my $password = '1234';
+my $borrowerFactory = t::lib::TestObjects::BorrowerFactory->new();
+my $borrowers = $borrowerFactory->createTestGroup([
+ {firstname => 'Testone',
+ surname => 'Testtwo',
+ cardnumber => '1A01',
+ branchcode => 'CPL',
+ userid => 'normal_user',
+ password => $password,
+ },
+ {firstname => 'Testthree',
+ surname => 'Testfour',
+ cardnumber => 'superuberadmin',
+ branchcode => 'CPL',
+ userid => 'god',
+ password => $password,
+ },
+ ], undef, $testContext);
+
+my $systempreferences = t::lib::TestObjects::SystemPreferenceFactory->createTestGroup([
+ {preference => 'ValidateEmailAddress',
+ value => 1
+ },
+ {preference => 'ValidatePhoneNumber',
+ value => 'ipn',
+ },
+ {preference => 'TalkingTechItivaPhoneNotification',
+ value => 1
+ },
+ {preference => 'SMSSendDriver',
+ value => 'test'
+ },
+ ], undef, $testContext);
+
+my $permissionManager = Koha::Auth::PermissionManager->new();
+$permissionManager->grantPermissions($borrowers->{'superuberadmin'}, {superlibrarian => 'superlibrarian'});
+
+eval {
+
+ # staff client
+ my $memberentry = t::lib::Page::Members::Memberentry->new({borrowernumber => $borrowers->{'superuberadmin'}->borrowernumber, op => 'modify', destination => 'circ', categorycode => 'PT'});
+ # opac
+ my $main = t::lib::Page::Opac::OpacMain->new({borrowernumber => $borrowers->{'superuberadmin'}->borrowernumber});
+
+ # set valid contacts and check preferences checkboxes
+ $memberentry->doPasswordLogin($borrowers->{'superuberadmin'}->userid(), $password)
+ ->setEmail("valid\@email.com")
+ ->checkPreferences(1, "email")
+ ->setPhone("+3585012345678")
+ ->checkPreferences(1, "phone")
+ ->setSMSNumber("+3585012345678")
+ ->checkPreferences(1, "sms")
+ ->submitForm(1) # expecting success
+ ->navigateToDetails()
+ # make sure everything is now checked on moremember.pl details page
+ ->checkMessagingPreferencesSet(1, "email", "sms", "phone");
+
+ $main # check that they are also checked in OPAC
+ ->doPasswordLogin($borrowers->{'superuberadmin'}->userid(), $password)
+ ->navigateYourMessaging()
+ ->checkMessagingPreferencesSet(1, "email", "sms", "phone");
+
+ # go to edit patron and set invalid contacts.
+ $memberentry
+ ->navigateEditPatron()
+ ->setEmail("invalidemail.com")
+ ->checkPreferences(0, "email")
+ ->setPhone("+3585012asd345678")
+ ->checkPreferences(0, "phone")
+ ->setSMSNumber("+358501asd2345678")
+ ->checkPreferences(0, "sms")
+ # check messaging preferences: they should be unchecked
+ ->checkMessagingPreferencesSet(0, "email", "sms", "phone")
+ ->submitForm(0) # also confirm that we cant submit the preferences
+ ->navigateToDetails()
+
+ # go to library use and just simply submit the form without any changes
+ ->navigateToLibraryUseEdit()
+ ->submitForm(1)
+ # all the preferences should be still set
+ ->navigateToDetails()
+ ->checkMessagingPreferencesSet(1, "email", "sms", "phone")
+
+ # go to smsnumber edit and make sure everything is checked
+ ->navigateToSMSnumberEdit()
+ ->checkMessagingPreferencesSet(1, "email", "sms", "phone")
+ ->submitForm(1)
+ ->navigateToDetails()
+ ->checkMessagingPreferencesSet(1, "email", "sms", "phone")
+
+ # go to patron information edit and clear email and phone
+ ->navigateToPatronInformationEdit()
+ ->clearMessagingContactFields("email", "phone")
+ ->submitForm(1)
+ ->navigateToDetails()
+ # this should remove our messaging preferences for phone and email
+ ->checkMessagingPreferencesSet(0, "email", "phone")
+ ->checkMessagingPreferencesSet(1, "sms"); # ... but not for sms (it's still set)
+
+ $main # check the preferences also from OPAC
+ ->navigateYourMessaging()
+ ->checkMessagingPreferencesSet(0, "email", "phone")
+ ->checkMessagingPreferencesSet(1, "sms");
+
+ # go to smsnumber edit and see that email and phone are disabled
+ $memberentry
+ ->navigateToSMSnumberEdit()
+ ->checkMessagingPreferencesSet(0, "email", "phone")
+ ->clearMessagingContactFields("SMSnumber") # uncheck all sms preferences
+ ->submitForm(1)
+ ->navigateToDetails()
+ ->checkMessagingPreferencesSet(0, "email", "phone", "sms");
+
+ $main # check the preferences also from OPAC
+ ->navigateYourMessaging()
+ ->checkMessagingPreferencesSet(0, "email", "phone", "sms");
+
+};
+if ($@) { #Catch all leaking errors and gracefully terminate.
+ warn $@;
+ tearDown();
+ exit 1;
+}
+
+##All tests done, tear down test context
+tearDown();
+done_testing;
+
+sub tearDown {
+ t::lib::TestObjects::ObjectFactory->tearDownTestContext($testContext);
+}
+
+
+
+
+
+
+
+
+######################################################
+ ### STARTING TEST IMPLEMENTATIONS ###
+######################################################
--