View | Details | Raw Unified | Return to bug 14590
Collapse All | Expand All

(-)a/C4/Form/MessagingPreferences.pm (-2 / +32 lines)
Lines 77-85 sub handle_form_action { Link Here
77
    # TODO: If a "NONE" box and another are checked somehow (javascript failed), we should pay attention to the "NONE" box
77
    # TODO: If a "NONE" box and another are checked somehow (javascript failed), we should pay attention to the "NONE" box
78
    my $prefs_set = 0;
78
    my $prefs_set = 0;
79
    OPTION: foreach my $option ( @$messaging_options ) {
79
    OPTION: foreach my $option ( @$messaging_options ) {
80
        my $updater = { %{ $target_params }, 
80
        my $updater = { borrowernumber          => $target_params->{'borrowernumber'},
81
                        message_attribute_id    => $option->{'message_attribute_id'} };
81
                        message_attribute_id    => $option->{'message_attribute_id'} };
82
        
82
        
83
        my @transport_methods = $query->param($option->{'message_attribute_id'});
84
        # Messaging preference validation. Make sure there is a valid contact information
85
        # provided for every transport method. Otherwise remove the transport method,
86
        # because the message cannot be delivered with this method!
87
        if ((defined $query->param('email') && !$query->param('email') ||
88
            !defined $query->param('email') && !$target_params->{'email'} && exists $target_params->{'email'})
89
            && (my $transport_id = (List::MoreUtils::firstidx { $_ eq "email" } @transport_methods)) >-1) {
90
91
            splice(@transport_methods, $transport_id, 1);# splice the email transport method for this message
92
        }
93
        if ((defined $query->param('phone') && !$query->param('phone') ||
94
            !defined $query->param('phone') && !$target_params->{'phone'} && exists $target_params->{'phone'})
95
            && (my $transport_id = (List::MoreUtils::firstidx { $_ eq "phone" } @transport_methods)) >-1) {
96
97
            splice(@transport_methods, $transport_id, 1);# splice the phone transport method for this message
98
        }
99
        if ((defined $query->param('SMSnumber') && !$query->param('SMSnumber') ||
100
            !defined $query->param('SMSnumber') && !$target_params->{'smsalertnumber'} && exists $target_params->{'smsalertnumber'})
101
            && (my $transport_id = (List::MoreUtils::firstidx { $_ eq "sms" } @transport_methods)) >-1) {
102
103
            splice(@transport_methods, $transport_id, 1);# splice the sms transport method for this message
104
        }
105
106
        if (@transport_methods > 0) {
107
            $query->param($option->{'message_attribute_id'}, @transport_methods);
108
        } else {
109
            $query->delete($option->{'message_attribute_id'});
110
        }
111
83
        # find the desired transports
112
        # find the desired transports
84
        @{$updater->{'message_transport_types'}} = $query->param( $option->{'message_attribute_id'} );
113
        @{$updater->{'message_transport_types'}} = $query->param( $option->{'message_attribute_id'} );
85
        next OPTION unless $updater->{'message_transport_types'};
114
        next OPTION unless $updater->{'message_transport_types'};
Lines 108-114 sub handle_form_action { Link Here
108
        C4::Members::Messaging::SetMessagingPreferencesFromDefaults( $target_params );
137
        C4::Members::Messaging::SetMessagingPreferencesFromDefaults( $target_params );
109
    }
138
    }
110
    # show the success message
139
    # show the success message
111
    $template->param( settings_updated => 1 );
140
    $template->param( settings_updated => 1 ) if (defined $template);
141
112
}
142
}
113
143
114
=head2 set_form_values
144
=head2 set_form_values
(-)a/C4/Members.pm (+9 lines)
Lines 656-661 sub ModMember { Link Here
656
            $data{password} = hash_password($data{password});
656
            $data{password} = hash_password($data{password});
657
        }
657
        }
658
    }
658
    }
659
659
    my $old_categorycode = GetBorrowerCategorycode( $data{borrowernumber} );
660
    my $old_categorycode = GetBorrowerCategorycode( $data{borrowernumber} );
660
661
661
    # get only the columns of a borrower
662
    # get only the columns of a borrower
Lines 686-691 sub ModMember { Link Here
686
            AddEnrolmentFeeIfNeeded( $data{categorycode}, $data{borrowernumber} );
687
            AddEnrolmentFeeIfNeeded( $data{categorycode}, $data{borrowernumber} );
687
        }
688
        }
688
689
690
        # Validate messaging preferences if any of the following field has been removed
691
        if ((not Koha::Validation::validate_email($data{email}) or
692
             not Koha::Validation::validate_phonenumber($data{phone})) and
693
             not exists $data{smsalertnumber}) {
694
            # Make sure there are no misconfigured preferences - if there is, delete them.
695
            C4::Members::Messaging::DeleteAllMisconfiguredPreferences($data{borrowernumber});
696
        }
697
689
        # If NorwegianPatronDBEnable is enabled, we set syncstatus to something that a
698
        # If NorwegianPatronDBEnable is enabled, we set syncstatus to something that a
690
        # cronjob will use for syncing with NL
699
        # cronjob will use for syncing with NL
691
        if ( C4::Context->preference('NorwegianPatronDBEnable') && C4::Context->preference('NorwegianPatronDBEnable') == 1 ) {
700
        if ( C4::Context->preference('NorwegianPatronDBEnable') && C4::Context->preference('NorwegianPatronDBEnable') == 1 ) {
(-)a/C4/Members/Messaging.pm (+114 lines)
Lines 20-25 package C4::Members::Messaging; Link Here
20
use strict;
20
use strict;
21
use warnings;
21
use warnings;
22
use C4::Context;
22
use C4::Context;
23
use Koha::Validation;
23
24
24
use vars qw($VERSION);
25
use vars qw($VERSION);
25
26
Lines 259-264 sub SetMessagingPreferencesFromDefaults { Link Here
259
    }
260
    }
260
}
261
}
261
262
263
=head2 DeleteAllMisconfiguredPreferences
264
265
  C4::Members::Messaging::DeleteAllMisconfiguredPreferences( [ $borrowernumber ] );
266
267
Deletes all misconfigured preferences for ALL borrowers that have invalid contact information for
268
the transport types. Given a borrowernumber, deletes misconfigured preferences only for this borrower.
269
270
return: returns array of arrayrefs to the deleted preferences (borrower_message_preference_id and message_transport_type)
271
272
=cut
273
274
sub DeleteAllMisconfiguredPreferences {
275
    my $borrowernumber = shift;
276
277
    my @deleted_prefs;
278
279
    push(@deleted_prefs, DeleteMisconfiguredPreference("email", "email", "email", $borrowernumber));
280
    push(@deleted_prefs, DeleteMisconfiguredPreference("phone", "phone", "phone", $borrowernumber));
281
    push(@deleted_prefs, DeleteMisconfiguredPreference("sms", "smsalertnumber", "phone", $borrowernumber));
282
283
    return @deleted_prefs;
284
}
285
286
=head2 DeleteMisconfiguredPreference
287
288
  C4::Members::Messaging::DeleteMisconfiguredPreference( $type, $contact, $validator [, $borrowernumber ] );
289
290
Takes a messaging preference type and the primary contact method for it, and a string to define
291
the Koha::Validation that should be used to determine whether the preference is misconfigured.
292
293
A messaging preference is misconfigured when it is linked with invalid contact information.
294
E.g. messaging type email expects the user to have a valid e-mail address in order to work.
295
296
Deletes misconfigured preferences for ALL borrowers that have invalid contact information for
297
that transport type. Given a borrowernumber, deletes misconfigured preferences only for this borrower.
298
299
return: returns array of arrayrefs to the deleted preferences (borrower_message_preference_id and message_transport_type)
300
301
=cut
302
303
sub DeleteMisconfiguredPreference {
304
    my ($type, $contact, $validator, $borrowernumber) = @_;
305
306
    if (not defined $type or not defined $contact or not defined $validator) {
307
        return 0;
308
    }
309
310
    my @misconfigured_prefs;
311
312
    # Get all messaging preferences and borrower's contact information
313
    my $dbh = C4::Context->dbh();
314
    my $query = "
315
316
        SELECT
317
                    borrower_message_preferences.borrower_message_preference_id,
318
                    borrower_message_transport_preferences.message_transport_type,
319
                    borrowers.$contact
320
321
        FROM
322
                    borrower_message_preferences,
323
                    borrower_message_transport_preferences,
324
                    borrowers
325
326
        WHERE
327
                    borrower_message_preferences.borrower_message_preference_id
328
                    =
329
                    borrower_message_transport_preferences.borrower_message_preference_id
330
331
        AND
332
                    borrowers.borrowernumber = borrower_message_preferences.borrowernumber
333
334
        AND
335
                    borrower_message_transport_preferences.message_transport_type = ?
336
    ";
337
338
    $query .= " AND borrowers.borrowernumber = ?" if defined $borrowernumber;
339
340
    my $sth = $dbh->prepare($query);
341
342
    if (defined $borrowernumber){
343
        $sth->execute($type, $borrowernumber);
344
    } else {
345
        $sth->execute($type);
346
    }
347
348
    while (my $ref = $sth->fetchrow_arrayref) {
349
        if ($$ref[1] eq $type) {
350
            my ($valid_contact, $err, $err_msg) = Koha::Validation::use_validator($validator, $$ref[2]);
351
            # push the misconfigured preferences into an array
352
            push(@misconfigured_prefs, $$ref[0]) unless $valid_contact and $$ref[2];
353
        }
354
    }
355
356
    $sth = $dbh->prepare("
357
358
    DELETE FROM
359
                    borrower_message_transport_preferences
360
361
    WHERE
362
                    borrower_message_preference_id = ? AND message_transport_type = ?
363
    ");
364
365
    my @deleted_prefs;
366
    foreach my $id (@misconfigured_prefs){
367
        # delete the misconfigured pref
368
        $sth->execute($id, $type);
369
        # push it into array that we will return
370
        push (@deleted_prefs, [$id,$type]);
371
    }
372
373
    return @deleted_prefs;
374
}
375
262
=head1 TABLES
376
=head1 TABLES
263
377
264
=head2 message_queue
378
=head2 message_queue
(-)a/Koha/Borrower/Modifications.pm (+9 lines)
Lines 26-31 use Modern::Perl; Link Here
26
26
27
use C4::Context;
27
use C4::Context;
28
use C4::Debug;
28
use C4::Debug;
29
use C4::Form::MessagingPreferences;
29
30
30
sub new {
31
sub new {
31
    my ( $class, %args ) = @_;
32
    my ( $class, %args ) = @_;
Lines 191-196 sub ApproveModifications { Link Here
191
        borrowernumber => $data->{borrowernumber},
192
        borrowernumber => $data->{borrowernumber},
192
    });
193
    });
193
    if( $rs->update($data) ) {
194
    if( $rs->update($data) ) {
195
        # Validate messaging preferences if any of the following field has been removed
196
        if ((not Koha::Validation::validate_email($data->{email}) or
197
             not Koha::Validation::validate_phonenumber($data->{phone}) or
198
             not Koha::Validation::validate_phonenumber($data->{'smsalertnumber'}))) {
199
            # Make sure there are no misconfigured preferences - if there is, delete them.
200
            C4::Members::Messaging::DeleteAllMisconfiguredPreferences($borrowernumber);
201
        }
202
194
        $self->DelModifications( { borrowernumber => $borrowernumber } );
203
        $self->DelModifications( { borrowernumber => $borrowernumber } );
195
    }
204
    }
196
}
205
}
(-)a/koha-tmpl/intranet-tmpl/prog/en/js/messaging-preference.js (+91 lines)
Line 0 Link Here
1
/**
2
 *
3
 * Used in: koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt
4
 *
5
 * This component is also used in OPAC: koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-messaging.tt
6
 * For modifications, edit also OPAC version in: koha-tmpl/opac-tmpl/bootstrap/en/js/messaging-preference.js
7
 *
8
 * Disables and clears checkboxes from messaging preferences
9
 * if there is either invalid or nonexistent contact information
10
 * for the message transfer type.
11
 *
12
 * @param {HTMLInputElement} elem
13
 *  The contact field
14
 * @param {string} id_attr
15
 *  Checkboxes' id attribute so that we can recognize them
16
 */
17
// Settings for messaging-preference.js
18
var patron_messaging_checkbox_preferences = {
19
    email: {
20
        checked_checkboxes: null,
21
        is_enabled: true,
22
        disabled_checkboxes: null
23
    },
24
    sms: {
25
        checked_checkboxes: null,
26
        is_enabled: true,
27
        disabled_checkboxes: null
28
    },
29
    phone: {
30
        checked_checkboxes: null,
31
        is_enabled: true,
32
        disabled_checkboxes: null
33
    }
34
};
35
36
function disableCheckboxesWithInvalidPreferences(elem, id_attr) {
37
    // Get checkbox preferences for the element
38
    var checkbox_prefs = eval("patron_messaging_checkbox_preferences." + id_attr);
39
    // Check if element is empty or not valid
40
41
    if (!$(elem).length || $(elem).val().length == 0 ||  !$(elem).valid()) {
42
43
        if (checkbox_prefs.is_enabled) {
44
            // Save the state of checked checkboxes
45
            checkbox_prefs.checked_checkboxes = $("input[type='checkbox'][id^=" + id_attr + "][value=" + id_attr + "]:checked");
46
47
            // Save the state of automatically disabled checkboxes
48
            // (We don't want to enable them once the e-mail is valid!)
49
            checkbox_prefs.disabled_checkboxes = $("input[type='checkbox'][id^=" + id_attr + "][value=" + id_attr + "]:disabled");
50
51
            // Clear patron messaging preferences checkboxes
52
            $("input[type='checkbox'][id^=" + id_attr + "][value=" + id_attr + "]").removeAttr("checked");
53
54
            // Then disable checkboxes from patron messaging perferences
55
            $("input[type='checkbox'][id^=" + id_attr + "][value=" + id_attr + "]").attr("disabled", "disabled");
56
57
            // Color table cell's background emphasize the disabled state of the checkbox
58
            $("input[type='checkbox'][id^=" + id_attr + "][value=" + id_attr + "]").parent().css("background-color", "#E8F0F8");
59
60
            // Show notice about missing contact in messaging preferences box
61
            $("#required-" + id_attr).css("display", "block");
62
63
            checkbox_prefs.is_enabled = false;
64
        }
65
    } else {
66
67
        if (!checkbox_prefs.is_enabled) {
68
            // Enable patron messaging preferences checkboxes
69
            $("input[type='checkbox'][id^=" + id_attr + "][value=" + id_attr + "]").removeAttr("disabled");
70
71
            // Disable the checkboxes that were disabled by default
72
            checkbox_prefs.disabled_checkboxes.each(function() {
73
                $(this).attr("disabled", "disabled");
74
                $(this).removeAttr("checked");
75
            });
76
77
            // Restore the state of checkboxes
78
            checkbox_prefs.checked_checkboxes.each(function() {
79
                $(this).attr("checked", "checked");
80
            });
81
82
            // Remove the background color from table cell
83
            $("input[type='checkbox'][id^=" + id_attr + "][value=" + id_attr + "]").parent().css("background-color", "#FFF");
84
85
            // Remove notice about missing contact from messaging preferences box
86
            $("#required-" + id_attr).css("display", "none");
87
88
            checkbox_prefs.is_enabled = true;
89
        }
90
    }
91
}
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt (-17 / +50 lines)
Lines 37-43 Link Here
37
37
38
        var MSG_INCORRECT_PHONE = _("Please enter a valid phone number.");
38
        var MSG_INCORRECT_PHONE = _("Please enter a valid phone number.");
39
        $.validator.addMethod('phone', function(value) {
39
        $.validator.addMethod('phone', function(value) {
40
            value = value.trim();
41
            if (!value.trim()) {
40
            if (!value.trim()) {
42
                return 1;
41
                return 1;
43
            }
42
            }
Lines 82-116 Link Here
82
                $("body, form input[type='submit'], form button[type='submit'], form a").addClass('waiting');
81
                $("body, form input[type='submit'], form button[type='submit'], form a").addClass('waiting');
83
                if (form.beenSubmitted)
82
                if (form.beenSubmitted)
84
                    return false;
83
                    return false;
85
                else
84
                else {
86
                    form.beenSubmitted = true;
85
                        form.beenSubmitted = true;
87
                    [% IF ValidateEmailAddress %]
86
                        [% IF ValidateEmailAddress %]
88
                        $("#email, #emailpro, #B_email").each(function(){
87
                        $("#email, #emailpro, #B_email").each(function(){
89
                            $(this).val($.trim($(this).val()));
88
                            $(this).val($.trim($(this).val()));
90
                        });
89
                        });
91
                    [% END %]
90
                        [% END %]
92
                    [% IF ValidatePhoneNumber %]
91
                        [% IF ValidatePhoneNumber %]
93
                        $("#phone, #phonepro, #B_phone, #SMSnumber").each(function(){
92
                        $("#phone, #phonepro, #B_phone, #SMSnumber").each(function(){
94
                            $(this).val($.trim($(this).val()));
93
                            $(this).val($.trim($(this).val()));
95
                        });
94
                        });
96
                    [% END %]
95
                        [% END %]
97
                    form.submit();
96
                        form.submit();
97
                    }
98
                }
98
                }
99
        });
99
        });
100
100
101
        [% IF ValidateEmailAddress %]
101
        [% IF ValidateEmailAddress %]
102
        $("#email, #emailpro, #B_email").on("change", function(){
102
            [% IF !email %]
103
            $(this).val($.trim($(this).val()));
103
                disableCheckboxesWithInvalidPreferences($("#email"), "email");
104
        });
104
            [% END %]
105
            $("#email").on("input", function(){
106
                disableCheckboxesWithInvalidPreferences($(this), "email");
107
            });
108
            $("#email, #emailpro, #B_email").on("change", function(){
109
                $(this).val($.trim($(this).val()));
110
                disableCheckboxesWithInvalidPreferences($(this), "email");
111
            });
105
        [% END %]
112
        [% END %]
113
106
        [% IF ValidatePhoneNumber %]
114
        [% IF ValidatePhoneNumber %]
107
        $("#SMSnumber").on("change", function(){
115
            [% IF !smsalertnumber %]
108
            $(this).val($.trim($(this).val()));
116
                disableCheckboxesWithInvalidPreferences($("#SMSnumber"), "sms");
109
        });
117
            [% END %]
110
        $("#phone, #phonepro, #B_phone").on("change", function(){
118
            [% IF !phone %]
111
            $(this).val($.trim($(this).val()));
119
                disableCheckboxesWithInvalidPreferences($("#phone"), "phone");
112
        });
120
            [% END %]
121
            $("#SMSnumber").on("input", function(){
122
                disableCheckboxesWithInvalidPreferences($(this), "sms");
123
            });
124
            $("#SMSnumber").on("change", function(){
125
                $(this).val($.trim($(this).val()));
126
                disableCheckboxesWithInvalidPreferences($(this), "sms");
127
            });
128
            $("#phone").on("input", function(){
129
                disableCheckboxesWithInvalidPreferences($(this), "phone");
130
            });
131
            $("#phone, #phonepro, #B_phone").on("change", function(){
132
                $(this).val($.trim($(this).val()));
133
                disableCheckboxesWithInvalidPreferences($(this), "phone");
134
            });
113
        [% END %]
135
        [% END %]
136
114
        var mrform = $("#manual_restriction_form");
137
        var mrform = $("#manual_restriction_form");
115
        var mrlink = $("#add_manual_restriction");
138
        var mrlink = $("#add_manual_restriction");
116
        mrform.hide();
139
        mrform.hide();
Lines 214-219 Link Here
214
//]]>
237
//]]>
215
</script>
238
</script>
216
<script type="text/javascript" src="[% themelang %]/js/members.js"></script>
239
<script type="text/javascript" src="[% themelang %]/js/members.js"></script>
240
<script type="text/javascript" src="[% themelang %]/js/messaging-preference.js"></script>
217
</head>
241
</head>
218
<body id="pat_memberentrygen" class="pat">
242
<body id="pat_memberentrygen" class="pat">
219
[% INCLUDE 'header.inc' %]
243
[% INCLUDE 'header.inc' %]
Lines 1157-1162 Link Here
1157
    </script>
1181
    </script>
1158
    [% END %]
1182
    [% END %]
1159
    <input type="hidden" name="setting_messaging_prefs" value="1" />
1183
    <input type="hidden" name="setting_messaging_prefs" value="1" />
1184
    [% IF ( ValidateEmailAddress ) %]
1185
    <p id="required-email" style="[% IF email %]display:none;[% END %]"><label for="email">Primary email</label> is required in order to set Email preferences.</p>
1186
    [% END %]
1187
    [% IF ( ValidatePhoneNumber ) %]
1188
    <p id="required-phone" style="[% IF phone %]display:none;[% END %]"><label for="phone">Primary phone</label> is required in order to set Phone preferences.</p>
1189
    [% IF ( SMSSendDriver ) %]
1190
    <p id="required-sms" style="[% IF smsalertnumber %]display:none;[% END %]"><label for="SMSnumber">SMS Number</label> is required in order to set SMS preferences.</p>
1191
    [% END %]
1192
    [% END %]
1160
    [% INCLUDE 'messaging-preference-form.inc' %]
1193
    [% INCLUDE 'messaging-preference-form.inc' %]
1161
    [% IF ( SMSSendDriver ) %]
1194
    [% IF ( SMSSendDriver ) %]
1162
        <p><label for="SMSnumber">SMS number:</label>
1195
        <p><label for="SMSnumber">SMS number:</label>
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-messaging.tt (-3 / +22 lines)
Lines 24-29 Link Here
24
            <div class="span10">
24
            <div class="span10">
25
                <div id="usermessaging">
25
                <div id="usermessaging">
26
                    <h3>Your messaging settings</h3>
26
                    <h3>Your messaging settings</h3>
27
                        <div id="required-email" class="alert" style="[% IF BORROWER_INF.email %]display:none;[% END %]"><h4>Primary email</h4> is required in order to set Email preferences.</div>
28
                        <div id="required-phone" class="alert" style="[% IF BORROWER_INF.phone %]display:none;[% END %]"><h4>Primary phone</h4> is required in order to set Phone preferences.</div>
29
                        <div id="required-sms" class="alert[% IF ( invalid_smsnumber ) %] alert-error[% END %]" style="[% IF BORROWER_INF.smsalertnumber %]display:none;[% END %]"><h4>SMS number</h4> [% IF ( invalid_smsnumber ) %]is not valid and cannot be saved[% ELSE %]is required in order to set SMS preferences[% END %].</div>
27
                    [% IF ( settings_updated ) %]
30
                    [% IF ( settings_updated ) %]
28
                        <div class="alert alert-success"><h4>Settings updated</h4></div>
31
                        <div class="alert alert-success"><h4>Settings updated</h4></div>
29
                    [% END %]
32
                    [% END %]
Lines 198-211 Link Here
198
        }
201
        }
199
    });
202
    });
200
203
204
    [% IF ( ValidateEmailAddress ) %]
205
        [% IF !BORROWER_INF.email %]
206
        disableCheckboxesWithInvalidPreferences($("#email"), "email");
207
        [% END %]
208
    [% END %]
201
    [% IF ( ValidatePhoneNumber ) %]
209
    [% IF ( ValidatePhoneNumber ) %]
202
    $("#SMSnumber").on("change", function(){
210
        [% IF !BORROWER_INF.smsalertnumber %]
211
        disableCheckboxesWithInvalidPreferences($("#SMSnumber"), "sms");
212
        [% END %]
213
        [% IF !BORROWER_INF.phone %]
214
        disableCheckboxesWithInvalidPreferences($("#phone"), "phone");
215
        [% END %]
216
217
        $("#SMSnumber").on("input", function(){
218
            disableCheckboxesWithInvalidPreferences($(this), "sms");
219
        });
220
        $("#SMSnumber").on("change", function(){
203
            $(this).val($.trim($(this).val()));
221
            $(this).val($.trim($(this).val()));
204
    });
222
            disableCheckboxesWithInvalidPreferences($(this), "sms");
223
        });
205
    [% END %]
224
    [% END %]
206
207
  });
225
  });
208
//]]>
226
//]]>
209
</script>
227
</script>
210
<script type="text/javascript" src="/opac-tmpl/bootstrap/lib/jquery/plugins/jquery.validate.min.js"></script>
228
<script type="text/javascript" src="/opac-tmpl/bootstrap/lib/jquery/plugins/jquery.validate.min.js"></script>
229
<script type="text/javascript" src="[% interface %]/[% theme %]/js/messaging-preference.js"></script>
211
[% END %]
230
[% END %]
(-)a/koha-tmpl/opac-tmpl/bootstrap/js/messaging-preference.js (+91 lines)
Line 0 Link Here
1
/**
2
 *
3
 * Used in: koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-messaging.tt
4
 *
5
 * This component is also used in Staff client: koha-tmpl/intranet-tmpl/prog/en/modules/memberentrygen.tt
6
 * For modifications, edit also Staff client version in: koha-tmpl/intranet-tmpl/prog/en/js/messaging-preference.js
7
 *
8
 * Disables and clears checkboxes from messaging preferences
9
 * if there is either invalid or nonexistent contact information
10
 * for the message transfer type.
11
 *
12
 * @param {HTMLInputElement} elem
13
 *  The contact field
14
 * @param {string} id_attr
15
 *  Checkboxes' id attribute so that we can recognize them
16
 */
17
// Settings for messaging-preference.js
18
var patron_messaging_checkbox_preferences = {
19
    email: {
20
        checked_checkboxes: null,
21
        is_enabled: true,
22
        disabled_checkboxes: null
23
    },
24
    sms: {
25
        checked_checkboxes: null,
26
        is_enabled: true,
27
        disabled_checkboxes: null
28
    },
29
    phone: {
30
        checked_checkboxes: null,
31
        is_enabled: true,
32
        disabled_checkboxes: null
33
    }
34
};
35
36
function disableCheckboxesWithInvalidPreferences(elem, id_attr) {
37
    // Get checkbox preferences for the element
38
    var checkbox_prefs = eval("patron_messaging_checkbox_preferences." + id_attr);
39
    // Check if element is empty or not valid
40
41
    if (!$(elem).length || $(elem).val().length == 0 ||  !$(elem).valid()) {
42
43
        if (checkbox_prefs.is_enabled) {
44
            // Save the state of checked checkboxes
45
            checkbox_prefs.checked_checkboxes = $("input[type='checkbox'][id^=" + id_attr + "][value=" + id_attr + "]:checked");
46
47
            // Save the state of automatically disabled checkboxes
48
            // (We don't want to enable them once the e-mail is valid!)
49
            checkbox_prefs.disabled_checkboxes = $("input[type='checkbox'][id^=" + id_attr + "][value=" + id_attr + "]:disabled");
50
51
            // Clear patron messaging preferences checkboxes
52
            $("input[type='checkbox'][id^=" + id_attr + "][value=" + id_attr + "]").removeAttr("checked");
53
54
            // Then disable checkboxes from patron messaging perferences
55
            $("input[type='checkbox'][id^=" + id_attr + "][value=" + id_attr + "]").attr("disabled", "disabled");
56
57
            // Color table cell's background emphasize the disabled state of the checkbox
58
            $("input[type='checkbox'][id^=" + id_attr + "][value=" + id_attr + "]").parent().css("background-color", "#E8F0F8");
59
60
            // Show notice about missing contact in messaging preferences box
61
            $("#required-" + id_attr).css("display", "block");
62
63
            checkbox_prefs.is_enabled = false;
64
        }
65
    } else {
66
67
        if (!checkbox_prefs.is_enabled) {
68
            // Enable patron messaging preferences checkboxes
69
            $("input[type='checkbox'][id^=" + id_attr + "][value=" + id_attr + "]").removeAttr("disabled");
70
71
            // Disable the checkboxes that were disabled by default
72
            checkbox_prefs.disabled_checkboxes.each(function() {
73
                $(this).attr("disabled", "disabled");
74
                $(this).removeAttr("checked");
75
            });
76
77
            // Restore the state of checkboxes
78
            checkbox_prefs.checked_checkboxes.each(function() {
79
                $(this).attr("checked", "checked");
80
            });
81
82
            // Remove the background color from table cell
83
            $("input[type='checkbox'][id^=" + id_attr + "][value=" + id_attr + "]").parent().css("background-color", "#FFF");
84
85
            // Remove notice about missing contact from messaging preferences box
86
            $("#required-" + id_attr).css("display", "none");
87
88
            checkbox_prefs.is_enabled = true;
89
        }
90
    }
91
}
(-)a/members/memberentry.pl (-1 / +1 lines)
Lines 441-447 if ((!$nok) and $nodouble and ($op eq 'insert' or $op eq 'save')){ Link Here
441
            C4::Members::Attributes::SetBorrowerAttributes($borrowernumber, $extended_patron_attributes);
441
            C4::Members::Attributes::SetBorrowerAttributes($borrowernumber, $extended_patron_attributes);
442
        }
442
        }
443
        if (C4::Context->preference('EnhancedMessagingPreferences') and $input->param('setting_messaging_prefs')) {
443
        if (C4::Context->preference('EnhancedMessagingPreferences') and $input->param('setting_messaging_prefs')) {
444
            C4::Form::MessagingPreferences::handle_form_action($input, { borrowernumber => $borrowernumber }, $template);
444
            C4::Form::MessagingPreferences::handle_form_action($input, \%data, $template);
445
        }
445
        }
446
	}
446
	}
447
	print scalar ($destination eq "circ") ? 
447
	print scalar ($destination eq "circ") ? 
(-)a/misc/maintenance/deleteMisconfiguredMessagingPrefs.pl (+213 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
#-----------------------------------
4
# Copyright 2015 Vaara-kirjastot
5
#
6
# This file is part of Koha.
7
#
8
# Koha is free software; you can redistribute it and/or modify it under the
9
# terms of the GNU General Public License as published by the Free Software
10
# Foundation; either version 2 of the License, or (at your option) any later
11
# version.
12
#
13
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
14
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License along
18
# with Koha; if not, write to the Free Software Foundation, Inc.,
19
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
#-----------------------------------
21
22
use strict;
23
use warnings;
24
use C4::Context;
25
use DBI;
26
use Email::Valid;
27
use POSIX qw(strftime);
28
use Getopt::Long;
29
use C4::Members::Messaging;
30
31
my $helptext = "
32
This script deletes misconfigured messaging preferences from the Koha database. A preference is
33
misconfigured if the user has no valid contact information for that type of transport method.
34
E.g user wants messages via e-mail while he has not provided an e-mail address.
35
36
Options:
37
    -h|--help           Prints this help documentation.
38
    -b|--backup:s       Filename for backup file. Required in 'restore' mode and optional in 'delete' mode.
39
                        Default value is messaging-prefs-backup_<date and time>. In 'delete' mode, if nothing
40
                        gets deleted, the file will not be created.
41
    -d|--delete         Activates the deletion mode (cannot be used simultaneously with mode 'restore').
42
    -r|--restore        Activates the restore mode (cannot be used simultaneously with mode 'delete').
43
    -m|--methods=s{1,3} Optional. Specifies the transfer methods/types. The three types are: email phone sms.
44
                        If not provided, all three types are used.
45
46
Examples:
47
    ./deleteMisconfiguredMessagingPrefs.pl -d -b
48
    ./deleteMisconfiguredMessagingPrefs.pl -d -t email phone -b
49
    ./deleteMisconfiguredMessagingPrefs.pl -d -t email phone sms -b my_backup_file
50
    ./deleteMisconfiguredMessagingPrefs.pl -r -b my_backup_file
51
\n";
52
53
my ($help, $delete, $filename, $restore, @methods);
54
55
GetOptions(
56
    'h|help' => \$help,
57
    'd|delete' => \$delete,
58
    'r|restore' => \$restore,
59
    'b|backup:s' => \$filename,
60
    'm|methods=s{1,3}' => \@methods
61
);
62
63
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();
64
my $are_we_doing_backups = 0;
65
66
67
if ($help || $restore && $delete || !$restore && !$delete) {
68
    die $helptext;
69
}
70
if ($delete and $filename eq "" or length($filename) > 0) {
71
    $are_we_doing_backups = 1;
72
    $filename = (strftime "messaging-prefs-backup_%Y-%m-%d_%H-%M-%S", localtime) if ($filename eq "");
73
}
74
75
76
77
78
79
80
81
82
83
84
85
86
if ($delete) {
87
    my @deleted_prefs;
88
89
    # check if user has specified messaging transport methods
90
    if (@methods > 0 && @methods < 4) {
91
        my $correct_modes = 0;
92
93
        foreach my $type (@methods){
94
95
            if ($type eq "email" or $type eq "phone" or $type eq "sms") {
96
                print "Deleting misconfigured $type messaging preferences\n";
97
98
                # method exists, don't need to print warning anymore
99
                $correct_modes = 1;
100
101
                # which contact info field (primary email / primary phone / smsalertnumber)
102
                # should we check?
103
                my $contact;
104
                $contact = "email" if $type eq "email";
105
                $contact = "phone" if $type eq "phone";
106
                $contact = "smsalertnumber" if $type eq "sms";
107
108
                # which validator should we use?
109
                my $validator;
110
                $validator = "email" if $type eq "email";
111
                $validator = "phone" if $type eq "phone" or $type eq "sms";
112
113
                # delete the misconfigured prefs and keep a counting them
114
                push(@deleted_prefs, C4::Members::Messaging::DeleteMisconfiguredPreference($type, $contact, $validator));
115
            }
116
        }
117
118
        die "Missing or invalid in parameter --type values. See help.\n$helptext" if $correct_modes == 0;
119
120
    } else {
121
122
        # user did not specify any methods. so let's delete them all!
123
        print "Deleting all misconfigured messaging preferences\n";
124
        push(@deleted_prefs, C4::Members::Messaging::DeleteAllMisconfiguredPreferences());
125
126
    }
127
128
    BackupDeletedPrefs(@deleted_prefs) if $are_we_doing_backups;
129
130
    print "Deleted ".scalar(@deleted_prefs)." misconfigured messaging preferences in total.\n";
131
}
132
elsif ($restore){
133
    if (@methods > 0) {
134
        my $correct_modes = 0;
135
        for (my $i=0; $i < @methods; $i++){
136
            if ($methods[$i] ne "email" and $methods[$i] ne "phone" and $methods[$i] ne "sms") {
137
                print "Invalid type $methods[$i]. Valid types are: email phone sms\n";
138
                splice(@methods, $i);
139
            }
140
        }
141
        die "Missing parameter --type values. See help.\n$helptext" if @methods == 0;
142
        RestoreDeletedPreferences(@methods);
143
    } else {
144
        RestoreDeletedPreferences();
145
    }
146
}
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# restoring deleted prefs
163
164
sub BackupDeletedPrefs {
165
    my @deleted = @_;
166
167
    open(my $fh, ">>", $filename) or die "Could not open file for writing.\n";
168
169
    for (my $i=0; $i < @deleted; $i++){
170
        say $fh $deleted[$i][0].",".$deleted[$i][1];
171
    }
172
}
173
sub RestoreDeletedPreferences {
174
    my $count = 0;
175
    my @methods = @_;
176
177
    my $dbh = C4::Context->dbh();
178
    open(my $fh, "<", $filename) or die "Could not open file for writing.\n";
179
180
    my $query = "INSERT INTO borrower_message_transport_preferences (borrower_message_preference_id, message_transport_type) VALUES (?,?)";
181
    my $sth = $dbh->prepare($query);
182
183
    # check if user has specified methods (types)
184
    if (@methods > 0) {
185
        while (my $line = <$fh>) {
186
            my @vars = split(',',$line);
187
            my @remlinebreak = split('\\n', $vars[1]);
188
            my $pref_id = $vars[0];
189
            my $type = $remlinebreak[0];
190
191
            if (grep(/$type/,@methods)) {
192
                $sth->execute($pref_id, $type) or $count--;
193
                $count++;
194
            }
195
        }
196
    } else {
197
        # simply walk through each line and restore every single line
198
        while (my $line = <$fh>) {
199
            my @vars = split(',',$line);
200
            next if @vars == 0;
201
            my @remlinebreak = split('\\n', $vars[1]);
202
            next if not defined $remlinebreak[0];
203
            my $pref_id = $vars[0];
204
            my $type = $remlinebreak[0];
205
206
            $sth->execute($pref_id, $type) or $count--;
207
            $count++;
208
        }
209
    }
210
211
    print "Restored $count preferences.\n";
212
213
}
(-)a/opac/opac-messaging.pl (-1 / +1 lines)
Lines 68-74 if ( defined $query->param('modify') && $query->param('modify') eq 'yes' ) { Link Here
68
        $borrower = GetMemberDetails( $borrowernumber );
68
        $borrower = GetMemberDetails( $borrowernumber );
69
    }
69
    }
70
70
71
    C4::Form::MessagingPreferences::handle_form_action($query, { borrowernumber => $borrowernumber }, $template);
71
    C4::Form::MessagingPreferences::handle_form_action($query, $borrower, $template);
72
}
72
}
73
73
74
C4::Form::MessagingPreferences::set_form_values({ borrowernumber     => $borrower->{'borrowernumber'} }, $template);
74
C4::Form::MessagingPreferences::set_form_values({ borrowernumber     => $borrower->{'borrowernumber'} }, $template);
(-)a/t/db_dependent/MessagingPreferencesValidation.t (-1 / +180 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/env perl
2
3
# Copyright 2015 Open Source Freedom Fighters
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
$ENV{KOHA_PAGEOBJECT_DEBUG} = 1;
20
use Modern::Perl;
21
22
use Test::More;
23
use Try::Tiny; #Even Selenium::Remote::Driver uses Try::Tiny :)
24
25
use Koha::Auth::PermissionManager;
26
27
use t::lib::Page::Mainpage;
28
use t::lib::Page::Opac::OpacMain;
29
use t::lib::Page::Opac::OpacMemberentry;
30
use t::lib::Page::Members::Memberentry;
31
use t::lib::Page::Members::Moremember;
32
33
use t::lib::TestObjects::BorrowerFactory;
34
use t::lib::TestObjects::SystemPreferenceFactory;
35
36
##Setting up the test context
37
my $testContext = {};
38
39
my $password = '1234';
40
my $borrowerFactory = t::lib::TestObjects::BorrowerFactory->new();
41
my $borrowers = $borrowerFactory->createTestGroup([
42
            {firstname  => 'Testone',
43
             surname    => 'Testtwo',
44
             cardnumber => '1A01',
45
             branchcode => 'CPL',
46
             userid     => 'normal_user',
47
             password   => $password,
48
            },
49
            {firstname  => 'Testthree',
50
             surname    => 'Testfour',
51
             cardnumber => 'superuberadmin',
52
             branchcode => 'CPL',
53
             userid     => 'god',
54
             password   => $password,
55
            },
56
        ], undef, $testContext);
57
58
my $systempreferences = t::lib::TestObjects::SystemPreferenceFactory->createTestGroup([
59
            {preference => 'ValidateEmailAddress',
60
             value      => 1
61
            },
62
            {preference => 'ValidatePhoneNumber',
63
             value      => 'ipn',
64
            },
65
            {preference => 'TalkingTechItivaPhoneNotification',
66
             value      => 1
67
            },
68
            {preference => 'SMSSendDriver',
69
             value      => 'test'
70
            },
71
        ], undef, $testContext);
72
73
my $permissionManager = Koha::Auth::PermissionManager->new();
74
$permissionManager->grantPermissions($borrowers->{'superuberadmin'}, {superlibrarian => 'superlibrarian'});
75
76
eval {
77
78
    # staff client
79
    my $memberentry = t::lib::Page::Members::Memberentry->new({borrowernumber => $borrowers->{'superuberadmin'}->borrowernumber, op => 'modify', destination => 'circ', categorycode => 'PT'});
80
    # opac
81
    my $main = t::lib::Page::Opac::OpacMain->new({borrowernumber => $borrowers->{'superuberadmin'}->borrowernumber});
82
83
    # set valid contacts and check preferences checkboxes
84
    $memberentry->doPasswordLogin($borrowers->{'superuberadmin'}->userid(), $password)
85
    ->setEmail("valid\@email.com")
86
    ->checkPreferences(1, "email")
87
    ->setPhone("+3585012345678")
88
    ->checkPreferences(1, "phone")
89
    ->setSMSNumber("+3585012345678")
90
    ->checkPreferences(1, "sms")
91
    ->submitForm(1) # expecting success
92
    ->navigateToDetails()
93
    # make sure everything is now checked on moremember.pl details page
94
    ->checkMessagingPreferencesSet(1, "email", "sms", "phone");
95
96
    $main # check that they are also checked in OPAC
97
    ->doPasswordLogin($borrowers->{'superuberadmin'}->userid(), $password)
98
    ->navigateYourMessaging()
99
    ->checkMessagingPreferencesSet(1, "email", "sms", "phone");
100
101
    # go to edit patron and set invalid contacts.
102
    $memberentry
103
    ->navigateEditPatron()
104
    ->setEmail("invalidemail.com")
105
    ->checkPreferences(0, "email")
106
    ->setPhone("+3585012asd345678")
107
    ->checkPreferences(0, "phone")
108
    ->setSMSNumber("+358501asd2345678")
109
    ->checkPreferences(0, "sms")
110
    # check messaging preferences: they should be unchecked
111
    ->checkMessagingPreferencesSet(0, "email", "sms", "phone")
112
    ->submitForm(0) # also confirm that we cant submit the preferences
113
    ->navigateToDetails()
114
115
    # go to library use and just simply submit the form without any changes
116
    ->navigateToLibraryUseEdit()
117
    ->submitForm(1)
118
    # all the preferences should be still set
119
    ->navigateToDetails()
120
    ->checkMessagingPreferencesSet(1, "email", "sms", "phone")
121
122
    # go to smsnumber edit and make sure everything is checked
123
    ->navigateToSMSnumberEdit()
124
    ->checkMessagingPreferencesSet(1, "email", "sms", "phone")
125
    ->submitForm(1)
126
    ->navigateToDetails()
127
    ->checkMessagingPreferencesSet(1, "email", "sms", "phone")
128
129
    # go to patron information edit and clear email and phone
130
    ->navigateToPatronInformationEdit()
131
    ->clearMessagingContactFields("email", "phone")
132
    ->submitForm(1)
133
    ->navigateToDetails()
134
    # this should remove our messaging preferences for phone and email
135
    ->checkMessagingPreferencesSet(0, "email", "phone")
136
    ->checkMessagingPreferencesSet(1, "sms"); # ... but not for sms (it's still set)
137
138
    $main # check the preferences also from OPAC
139
    ->navigateYourMessaging()
140
    ->checkMessagingPreferencesSet(0, "email", "phone")
141
    ->checkMessagingPreferencesSet(1, "sms");
142
143
    # go to smsnumber edit and see that email and phone are disabled
144
    $memberentry
145
    ->navigateToSMSnumberEdit()
146
    ->checkMessagingPreferencesSet(0, "email", "phone")
147
    ->clearMessagingContactFields("SMSnumber") # uncheck all sms preferences
148
    ->submitForm(1)
149
    ->navigateToDetails()
150
    ->checkMessagingPreferencesSet(0, "email", "phone", "sms");
151
152
    $main # check the preferences also from OPAC
153
    ->navigateYourMessaging()
154
    ->checkMessagingPreferencesSet(0, "email", "phone", "sms");
155
156
};
157
if ($@) { #Catch all leaking errors and gracefully terminate.
158
    warn $@;
159
    tearDown();
160
    exit 1;
161
}
162
163
##All tests done, tear down test context
164
tearDown();
165
done_testing;
166
167
sub tearDown {
168
    t::lib::TestObjects::ObjectFactory->tearDownTestContext($testContext);
169
}
170
171
172
173
174
175
176
177
178
######################################################
179
    ###  STARTING TEST IMPLEMENTATIONS         ###
180
######################################################

Return to bug 14590