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

(-)a/Bug-14620-Contact-information-validations.patch (+648 lines)
Line 0 Link Here
1
From 42e664f126d763a63db655df9a6807113d0f3dde Mon Sep 17 00:00:00 2001
2
From: Lari Taskula <lari.taskula@jns.fi>
3
Date: Tue, 4 Apr 2017 14:00:31 +0000
4
Subject: [PATCH] Bug 14620: Contact information validations
5
6
This patch adds a phone number validation by regex and centralizes
7
different validation methods into Koha::Validation class.
8
9
Introduces a new system preference, ValidatePhoneNumber, that takes a
10
regular expression and uses it to validate phone numbers both client
11
and server side.
12
13
Unit tests to test:
14
1. prove t/db_dependent/Koha/Validation.t
15
16
To test:
17
1. Apply the patches and run updatedatabase.pl to install the new
18
   system preference
19
2. Set system preference ValidatePhoneNumber to any regex you like
20
   (there is an example in the description of the preference)
21
3. Navigate to edit user contact informations in Staff client and OPAC.
22
4. Insert invalid email (e.g. "invalid") and invalid phone number ("+123invalid")
23
   and send the form.
24
5. Confirm that form will not be submitted and errors will be given.
25
6. Disable JavaScript and test that these errors will also be provided by the
26
   server.
27
---
28
 Koha/Validation.pm                                 | 80 ++++++++++++++++++++++
29
 .../Bug_14620-Contact-information-validation.perl  |  7 ++
30
 installer/data/mysql/sysprefs.sql                  |  1 +
31
 .../prog/en/modules/admin/preferences/patrons.pref |  9 +++
32
 .../prog/en/modules/members/memberentrygen.tt      | 25 +++++++
33
 koha-tmpl/intranet-tmpl/prog/js/members.js         | 28 ++++++++
34
 .../bootstrap/en/modules/opac-memberentry.tt       | 37 ++++++++++
35
 .../bootstrap/en/modules/opac-messaging.tt         | 44 ++++++++++++
36
 members/memberentry.pl                             | 32 +++++----
37
 opac/opac-memberentry.pl                           | 21 ++++--
38
 opac/opac-messaging.pl                             | 13 +++-
39
 t/db_dependent/Koha/Validation.t                   | 76 ++++++++++++++++++++
40
 12 files changed, 353 insertions(+), 20 deletions(-)
41
 create mode 100644 Koha/Validation.pm
42
 create mode 100644 installer/data/mysql/atomicupdate/Bug_14620-Contact-information-validation.perl
43
 create mode 100644 t/db_dependent/Koha/Validation.t
44
45
diff --git a/Koha/Validation.pm b/Koha/Validation.pm
46
new file mode 100644
47
index 0000000000..94006d88bd
48
--- /dev/null
49
+++ b/Koha/Validation.pm
50
@@ -0,0 +1,80 @@
51
+package Koha::Validation;
52
+
53
+# Copyright 2017 Koha-Suomi Oy
54
+#
55
+# This file is part of Koha.
56
+#
57
+# Koha is free software; you can redistribute it and/or modify it under the
58
+# terms of the GNU General Public License as published by the Free Software
59
+# Foundation; either version 2 of the License, or (at your option) any later
60
+# version.
61
+#
62
+# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
63
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
64
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
65
+#
66
+# You should have received a copy of the GNU General Public License along
67
+# with Koha; if not, write to the Free Software Foundation, Inc.,
68
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
69
+
70
+use Modern::Perl;
71
+
72
+use C4::Context;
73
+use Email::Valid;
74
+
75
+=head1 NAME
76
+
77
+Koha::Validation - validates inputs
78
+
79
+=head1 SYNOPSIS
80
+
81
+  use Koha::Validation
82
+
83
+=head1 DESCRIPTION
84
+
85
+This module lets you validate given inputs.
86
+
87
+=head2 METHODS
88
+
89
+=head3 email
90
+
91
+Koha::Validation::email("email@address.com");
92
+
93
+Validates given email.
94
+
95
+returns: 1 if the given email is valid (or empty), 0 otherwise.
96
+
97
+=cut
98
+
99
+sub email {
100
+    my $address = shift;
101
+
102
+    return 1 unless $address;
103
+    return 0 if $address =~ /(^(\s))|((\s)$)/;
104
+
105
+    return (not defined Email::Valid->address($address)) ? 0:1;
106
+}
107
+
108
+=head3 phone
109
+
110
+Koha::Validation::validate_phonenumber(123456789);
111
+
112
+Validates given phone number.
113
+
114
+returns: 1 if the given phone number is valid (or empty), 0 otherwise.
115
+
116
+=cut
117
+
118
+sub phone {
119
+    my $phonenumber = shift;
120
+
121
+    return 1 unless $phonenumber;
122
+    return 0 if $phonenumber =~ /(^(\s))|((\s)$)/;
123
+
124
+    my $regex = C4::Context->preference("ValidatePhoneNumber");
125
+    $regex = qr/$regex/;
126
+
127
+    return ($phonenumber !~ /$regex/) ? 0:1;
128
+}
129
+
130
+1;
131
diff --git a/installer/data/mysql/atomicupdate/Bug_14620-Contact-information-validation.perl b/installer/data/mysql/atomicupdate/Bug_14620-Contact-information-validation.perl
132
new file mode 100644
133
index 0000000000..d816b0ca80
134
--- /dev/null
135
+++ b/installer/data/mysql/atomicupdate/Bug_14620-Contact-information-validation.perl
136
@@ -0,0 +1,7 @@
137
+$DBversion = 'XXX';  # will be replaced by the RM
138
+if( CheckVersion( $DBversion ) ) {
139
+    $dbh->do("INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, `type` ) VALUES ('ValidatePhoneNumber','','','Regex for validation of patron phone numbers.','Textarea')");
140
+
141
+    SetVersion( $DBversion );
142
+    print "Upgrade to $DBversion done (Bug 14620 - description)\n";
143
+}
144
diff --git a/installer/data/mysql/sysprefs.sql b/installer/data/mysql/sysprefs.sql
145
index bc08b5a5d3..04bd7fd810 100644
146
--- a/installer/data/mysql/sysprefs.sql
147
+++ b/installer/data/mysql/sysprefs.sql
148
@@ -576,6 +576,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, `
149
 ('UseQueryParser','0',NULL,'If enabled, try to use QueryParser for queries.','YesNo'),
150
 ('UseTransportCostMatrix','0','','Use Transport Cost Matrix when filling holds','YesNo'),
151
 ('UseWYSIWYGinSystemPreferences','0','','Show WYSIWYG editor when editing certain HTML system preferences.','YesNo'),
152
+('ValidatePhoneNumber','','','Regex for validation of patron phone numbers.','Textarea'),
153
 ('viewISBD','1','','Allow display of ISBD view of bibiographic records','YesNo'),
154
 ('viewLabeledMARC','0','','Allow display of labeled MARC view of bibiographic records','YesNo'),
155
 ('viewMARC','1','','Allow display of MARC view of bibiographic records','YesNo'),
156
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref
157
index 3a95ba71aa..867bfe45e7 100644
158
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref
159
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref
160
@@ -219,3 +219,12 @@ Patrons:
161
          - pref: FailedLoginAttempts
162
            class: integer
163
          - failed login attempts.
164
+     -
165
+         - Use the following regex /
166
+         - pref: ValidatePhoneNumber
167
+           type: textarea
168
+           class: code
169
+         - / to validate patrons' phone numbers.
170
+         - Example ^((\+)?[1-9]{1,2})?([-\s\.])?((\(\d{1,4}\))|\d{1,4})(([-\s\.])?[0-9]{1,12}){1,2}$
171
+         - (Source of example http://regexlib.com/REDetails.aspx?regexp_id=3009)
172
+         - Leave blank to accept any phone number.
173
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt
174
index 091486efca..874da57ace 100644
175
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt
176
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt
177
@@ -62,6 +62,19 @@ $(document).ready(function() {
178
         $(".toggler").toggle();
179
     });
180
 
181
+
182
+    var MSG_INCORRECT_PHONE = _("Please enter a valid phone number.");
183
+    $.validator.addMethod('phone', function(value) {
184
+        value = value.trim();
185
+        if (!value.trim()) {
186
+            return 1;
187
+        }
188
+        else {
189
+            return (value.match(/[% ValidatePhoneNumber %]/));
190
+        }
191
+    },
192
+    MSG_INCORRECT_PHONE);
193
+
194
     $("#save_quick_add").click(function(){
195
         $("#quick_add_form").validate();
196
         if( $("#quick_add_form").valid()){
197
@@ -201,6 +214,18 @@ $(document).ready(function() {
198
             [% IF ERROR_bad_email_alternative %]
199
                 <li id="ERROR_bad_email_alternative">The alternative email is invalid.</li>
200
             [% END %]
201
+            [% IF ERROR_bad_phone %]
202
+                <li id="ERROR_bad_phone">The primary phone is invalid.</li>
203
+            [% END %]
204
+            [% IF ERROR_bad_phone_secondary %]
205
+                <li id="ERROR_bad_phone_secondary">The secondary phone is invalid.</li>
206
+            [% END %]
207
+            [% IF ERROR_bad_phone_alternative %]
208
+                <li id="ERROR_bad_phone_alternative">The alternative phone is invalid.</li>
209
+            [% END %]
210
+            [% IF ERROR_bad_smsnumber %]
211
+                <li id="ERROR_bad_smsnumber">The SMS number is invalid.</li>
212
+            [% END %]
213
 			</ul>
214
 		</div>
215
 	[% END %]
216
diff --git a/koha-tmpl/intranet-tmpl/prog/js/members.js b/koha-tmpl/intranet-tmpl/prog/js/members.js
217
index 2ced2eca8b..bfb8376820 100644
218
--- a/koha-tmpl/intranet-tmpl/prog/js/members.js
219
+++ b/koha-tmpl/intranet-tmpl/prog/js/members.js
220
@@ -333,6 +333,21 @@ $(document).ready(function(){
221
             },
222
             B_email: {
223
                 email: true
224
+            },
225
+            phone: {
226
+                phone: true
227
+            },
228
+            phonepro: {
229
+                phone: true
230
+            },
231
+            mobile: {
232
+                phone: true
233
+            },
234
+            SMSnumber: {
235
+                phone: true
236
+            },
237
+            B_phone: {
238
+                phone: true
239
             }
240
         },
241
         submitHandler: function(form) {
242
@@ -341,10 +356,23 @@ $(document).ready(function(){
243
                 return false;
244
             else
245
                 form.beenSubmitted = true;
246
+                $("#email, #emailpro, #B_email").each(function(){
247
+                    $(this).val($.trim($(this).val()));
248
+                });
249
+                $("#phone, #phonepro, #B_phone, #SMSnumber").each(function(){
250
+                    $(this).val($.trim($(this).val()));
251
+                });
252
                 form.submit();
253
             }
254
     });
255
 
256
+    $("#email, #emailpro, #B_email").each(function(){
257
+        $(this).val($.trim($(this).val()));
258
+    });
259
+    $("#phone, #phonepro, #B_phone, #SMSnumber").each(function(){
260
+        $(this).val($.trim($(this).val()));
261
+    });
262
+
263
     var mrform = $("#manual_restriction_form");
264
     var mrlink = $("#add_manual_restriction");
265
     mrform.hide();
266
diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-memberentry.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-memberentry.tt
267
index d3b89bfdbb..efa392235d 100644
268
--- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-memberentry.tt
269
+++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-memberentry.tt
270
@@ -64,6 +64,10 @@
271
                                 [% IF field == "email" %]<li>Contact information: <a href="#borrower_email">primary email address</a></li>[% END %]
272
                                 [% IF field == "emailpro" %]<li>Contact information: <a href="#borrower_emailpro">secondary email address</a></li>[% END %]
273
                                 [% IF field == "B_email" %]<li>Alternate address information: <a href="#borrower_B_email">email address</a></li>[% END %]
274
+                                [% IF field == "phone" %]<li>Contact information: <a href="#borrower_phone">primary phone</a></li>[% END %]
275
+                                [% IF field == "phonepro" %]<li>Contact information: <a href="#borrower_phonepro">secondary phone</a></li>[% END %]
276
+                                [% IF field == "mobile" %]<li>Contact information: <a href="#borrower_mobile">other phone</a></li>[% END %]
277
+                                [% IF field == "B_phone" %]<li>Alternate address information: <a href="#borrower_B_phone">phone</a></li>[% END %]
278
                                 [% IF field == "password_match" %]<li>Passwords do not match! <a href="#password">password</a></li>[% END %]
279
                                 [% IF field == "password_invalid" %]<li>Password does not meet minimum requirements! <a href="#password">password</a></li>[% END %]
280
                                 [% IF field == "password_spaces" %]<li>Password contains leading and/or trailing spaces! <a href="#password">password</a></li>[% END %]
281
@@ -943,6 +947,17 @@
282
                 $('label.required').removeClass('required');
283
             [% END %]
284
 
285
+            var MSG_INCORRECT_PHONE = _("Please enter a valid phone number.");
286
+            $.validator.addMethod('phone', function(value) {
287
+                if (!value.trim()) {
288
+                    return 1;
289
+                }
290
+                else {
291
+                    return (value.match(/[% ValidatePhoneNumber %]/));
292
+                }
293
+            },
294
+            MSG_INCORRECT_PHONE);
295
+
296
             $("#memberentry-form").validate({
297
                 rules: {
298
                     borrower_email: {
299
@@ -953,6 +968,18 @@
300
                     },
301
                     borrower_B_email: {
302
                         email: true
303
+                    },
304
+                    borrower_phone: {
305
+                        phone: true
306
+                    },
307
+                    borrower_phonepro: {
308
+                        phone: true
309
+                    },
310
+                    borrower_mobile: {
311
+                        phone: true
312
+                    },
313
+                    borrower_B_phone: {
314
+                        phone: true
315
                     }
316
                 },
317
                 submitHandler: function(form) {
318
@@ -961,6 +988,12 @@
319
                     }
320
                     else {
321
                         form.beenSubmitted = true;
322
+                        $("#borrower_email, #borrower_emailpro, #borrower_B_email").each(function(){
323
+                            $(this).val($.trim($(this).val()));
324
+                        });
325
+                        $("#borrower_phone, #borrower_phonepro, #borrower_B_phone").each(function(){
326
+                            $(this).val($.trim($(this).val()));
327
+                        });
328
                         form.submit();
329
                     }
330
                 },
331
@@ -975,6 +1008,10 @@
332
                 }
333
             });
334
 
335
+            $("#borrower_email, #borrower_emailpro, #borrower_B_email, #borrower_phone, #borrower_phonepro, #borrower_B_phone").on("change", function(){
336
+                $(this).val($.trim($(this).val()));
337
+            });
338
+
339
             [% IF borrower.guarantorid && !Koha.Preference('OPACPrivacy') && Koha.Preference('AllowPatronToSetCheckoutsVisibilityForGuarantor') %]
340
                 $('#update_privacy_guarantor_checkouts').click( function() {
341
                     $.post( "/cgi-bin/koha/svc/patron/show_checkouts_to_relatives", { privacy_guarantor_checkouts: $('#privacy_guarantor_checkouts').val() }, null, 'json')
342
diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-messaging.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-messaging.tt
343
index 801389c97c..a28918f6ba 100644
344
--- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-messaging.tt
345
+++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-messaging.tt
346
@@ -28,6 +28,9 @@
347
                     [% IF ( settings_updated ) %]
348
                         <div class="alert alert-success"><h4>Settings updated</h4></div>
349
                     [% END %]
350
+                    [% IF ( invalid_smsnumber ) %]
351
+                        <div class="alert alert-error"><h4>Invalid SMS number</h4></div>
352
+                    [% END %]
353
                     <form action="/cgi-bin/koha/opac-messaging.pl" method="get" name="opacmessaging">
354
                         <input type="hidden" name="modify" value="yes" />
355
 
356
@@ -184,7 +187,48 @@
357
       }
358
     });
359
     $("#info_digests").tooltip();
360
+
361
+    var MSG_INCORRECT_PHONE = _("Please enter a valid phone number.");
362
+    $.validator.addMethod('phone', function(value) {
363
+        if (!value.trim()) {
364
+            return 1;
365
+        }
366
+        else {
367
+            return (value.match(/[% ValidatePhoneNumber %]/));
368
+        }
369
+    },
370
+    MSG_INCORRECT_PHONE);
371
+
372
+    $("form[name='opacmessaging']").validate({
373
+        rules: {
374
+            SMSnumber: {
375
+                phone: true
376
+            }
377
+        },
378
+        submitHandler: function(form) {
379
+            $("body, form input[type='submit'], form button[type='submit'], form a").addClass('waiting');
380
+            if (form.beenSubmitted) {
381
+                return false;
382
+            }
383
+            else {
384
+                form.beenSubmitted = true;
385
+                $("#SMSnumber").each(function(){
386
+                    $(this).val($.trim($(this).val()));
387
+                });
388
+                form.submit();
389
+            }
390
+        },
391
+        errorPlacement: function(error, element) {
392
+            error.insertAfter(element.closest("li")).wrap('<li></li>');
393
+            error.addClass('alert-error');
394
+            error.width("auto");
395
+        }
396
+    });
397
+    $("#SMSnumber").on("change", function(){
398
+        $(this).val($.trim($(this).val()));
399
+    });
400
   });
401
 //]]>
402
 </script>
403
+<script type="text/javascript" src="/opac-tmpl/bootstrap/lib/jquery/plugins/jquery.validate.min.js"></script>
404
 [% END %]
405
diff --git a/members/memberentry.pl b/members/memberentry.pl
406
index c58b2a9bff..24857089fa 100755
407
--- a/members/memberentry.pl
408
+++ b/members/memberentry.pl
409
@@ -47,7 +47,7 @@ use Koha::Patron::Categories;
410
 use Koha::Patron::HouseboundRole;
411
 use Koha::Patron::HouseboundRoles;
412
 use Koha::Token;
413
-use Email::Valid;
414
+use Koha::Validation;
415
 use Module::Load;
416
 if ( C4::Context->preference('NorwegianPatronDBEnable') && C4::Context->preference('NorwegianPatronDBEnable') == 1 ) {
417
     load Koha::NorwegianPatronDB, qw( NLGetSyncDataFromBorrowernumber );
418
@@ -363,19 +363,13 @@ if ($op eq 'save' || $op eq 'insert'){
419
   push @errors, "ERROR_short_password" if( $password && $minpw && $password ne '****' && (length($password) < $minpw) );
420
 
421
   # Validate emails
422
-  my $emailprimary = $input->param('email');
423
-  my $emailsecondary = $input->param('emailpro');
424
-  my $emailalt = $input->param('B_email');
425
-
426
-  if ($emailprimary) {
427
-      push (@errors, "ERROR_bad_email") if (!Email::Valid->address($emailprimary));
428
-  }
429
-  if ($emailsecondary) {
430
-      push (@errors, "ERROR_bad_email_secondary") if (!Email::Valid->address($emailsecondary));
431
-  }
432
-  if ($emailalt) {
433
-      push (@errors, "ERROR_bad_email_alternative") if (!Email::Valid->address($emailalt));
434
-  }
435
+  push (@errors, "ERROR_bad_email") if ($input->param('email') && !Koha::Validation::email($input->param('email')));
436
+  push (@errors, "ERROR_bad_email_secondary") if ($input->param('emailpro') && !Koha::Validation::email($input->param('emailpro')));
437
+  push (@errors, "ERROR_bad_email_alternative") if ($input->param('B_email') && !Koha::Validation::email($input->param('B_email')));
438
+  # Validate phone numbers
439
+  push (@errors, "ERROR_bad_phone") if ($input->param('phone') && !Koha::Validation::phone($input->param('phone')));
440
+  push (@errors, "ERROR_bad_phone_secondary") if ($input->param('phonepro') && !Koha::Validation::phone($input->param('phonepro')));
441
+  push (@errors, "ERROR_bad_phone_alternative") if ($input->param('B_phone') && !Koha::Validation::phone($input->param('B_phone')));
442
 
443
   if (C4::Context->preference('ExtendedPatronAttributes')) {
444
     $extended_patron_attributes = parse_extended_patron_attributes($input);
445
@@ -403,7 +397,11 @@ if ( ($op eq 'modify' || $op eq 'insert' || $op eq 'save'|| $op eq 'duplicate')
446
 # BZ 14683: Do not mixup mobile [read: other phone] with smsalertnumber
447
 my $sms = $input->param('SMSnumber');
448
 if ( defined $sms ) {
449
-    $newdata{smsalertnumber} = $sms;
450
+    if (Koha::Validation::phone($sms)){
451
+        $newdata{smsalertnumber} = $sms;
452
+    } else {
453
+        push (@errors, "ERROR_bad_smsnumber");
454
+    }
455
 }
456
 
457
 ###  Error checks should happen before this line.
458
@@ -720,6 +718,10 @@ if (C4::Context->preference('ExtendedPatronAttributes')) {
459
     patron_attributes_form($template, $borrowernumber);
460
 }
461
 
462
+$template->param(
463
+    ValidatePhoneNumber  => C4::Context->preference('ValidatePhoneNumber') || '.*',
464
+);
465
+
466
 if (C4::Context->preference('EnhancedMessagingPreferences')) {
467
     if ($op eq 'add') {
468
         C4::Form::MessagingPreferences::set_form_values({ categorycode => $categorycode }, $template);
469
diff --git a/opac/opac-memberentry.pl b/opac/opac-memberentry.pl
470
index 9784a3deef..7dba2d9575 100755
471
--- a/opac/opac-memberentry.pl
472
+++ b/opac/opac-memberentry.pl
473
@@ -29,7 +29,6 @@ use C4::Members;
474
 use C4::Members::Attributes qw( GetBorrowerAttributes );
475
 use C4::Form::MessagingPreferences;
476
 use C4::Scrubber;
477
-use Email::Valid;
478
 use Koha::DateUtils;
479
 use Koha::Libraries;
480
 use Koha::Patron::Attribute::Types;
481
@@ -39,6 +38,7 @@ use Koha::Patron::Modification;
482
 use Koha::Patron::Modifications;
483
 use Koha::Patrons;
484
 use Koha::Token;
485
+use Koha::Validation;
486
 
487
 my $cgi = new CGI;
488
 my $dbh = C4::Context->dbh;
489
@@ -88,6 +88,7 @@ $template->param(
490
     mandatory         => $mandatory,
491
     libraries         => \@libraries,
492
     OPACPatronDetails => C4::Context->preference('OPACPatronDetails'),
493
+    ValidatePhoneNumber   => C4::Context->preference('ValidatePhoneNumber') || '.*',
494
 );
495
 
496
 my $attributes = ParsePatronAttributes($borrowernumber,$cgi);
497
@@ -390,7 +391,7 @@ sub CheckForInvalidFields {
498
     my $borrower = shift;
499
     my @invalidFields;
500
     if ($borrower->{'email'}) {
501
-        unless ( Email::Valid->address($borrower->{'email'}) ) {
502
+        unless ( Koha::Validation::email($borrower->{'email'}) ) {
503
             push(@invalidFields, "email");
504
         } elsif ( C4::Context->preference("PatronSelfRegistrationEmailMustBeUnique") ) {
505
             my $patrons_with_same_email = Koha::Patrons->search(
506
@@ -410,10 +411,22 @@ sub CheckForInvalidFields {
507
         }
508
     }
509
     if ($borrower->{'emailpro'}) {
510
-        push(@invalidFields, "emailpro") if (!Email::Valid->address($borrower->{'emailpro'}));
511
+        push(@invalidFields, "emailpro") if (!Koha::Validation::email($borrower->{'emailpro'}));
512
     }
513
     if ($borrower->{'B_email'}) {
514
-        push(@invalidFields, "B_email") if (!Email::Valid->address($borrower->{'B_email'}));
515
+        push(@invalidFields, "B_email") if (!Koha::Validation::email($borrower->{'B_email'}));
516
+    }
517
+    if ($borrower->{'mobile'}) {
518
+        push(@invalidFields, "mobile") if (!Koha::Validation::phone($borrower->{'mobile'}));
519
+    }
520
+    if ($borrower->{'phone'}) {
521
+        push(@invalidFields, "phone") if (!Koha::Validation::phone($borrower->{'phone'}));
522
+    }
523
+    if ($borrower->{'phonepro'}) {
524
+        push(@invalidFields, "phonepro") if (!Koha::Validation::phone($borrower->{'phonepro'}));
525
+    }
526
+    if ($borrower->{'B_phone'}) {
527
+        push(@invalidFields, "B_phone") if (!Koha::Validation::phone($borrower->{'B_phone'}));
528
     }
529
     if ( defined $borrower->{'password'}
530
         and $borrower->{'password'} ne $borrower->{'password2'} )
531
diff --git a/opac/opac-messaging.pl b/opac/opac-messaging.pl
532
index 906d56fe4e..f360b4bcd7 100755
533
--- a/opac/opac-messaging.pl
534
+++ b/opac/opac-messaging.pl
535
@@ -31,6 +31,7 @@ use C4::Members;
536
 use C4::Members::Messaging;
537
 use C4::Form::MessagingPreferences;
538
 use Koha::SMS::Providers;
539
+use Koha::Validation;
540
 
541
 my $query = CGI->new();
542
 
543
@@ -53,10 +54,20 @@ my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
544
 my $borrower = Koha::Patrons->find( $borrowernumber )->unblessed;
545
 my $messaging_options = C4::Members::Messaging::GetMessagingOptions();
546
 
547
+my $validate_phone = C4::Context->preference('ValidatePhoneNumber');
548
+
549
+$template->param(
550
+    ValidatePhoneNumber    => $validate_phone || '.*',
551
+);
552
+
553
 if ( defined $query->param('modify') && $query->param('modify') eq 'yes' ) {
554
     my $sms = $query->param('SMSnumber');
555
     my $sms_provider_id = $query->param('sms_provider_id');
556
-    if ( defined $sms && ( $borrower->{'smsalertnumber'} // '' ) ne $sms
557
+
558
+    my $valid_sms = Koha::Validation::phone($sms);
559
+    $template->param( invalid_smsnumber => 1 ) unless $valid_sms;
560
+
561
+    if ( defined $sms && $valid_sms && ( $borrower->{'smsalertnumber'} // '' ) ne $sms
562
             or ( $borrower->{sms_provider_id} // '' ) ne $sms_provider_id ) {
563
         ModMember(
564
             borrowernumber  => $borrowernumber,
565
diff --git a/t/db_dependent/Koha/Validation.t b/t/db_dependent/Koha/Validation.t
566
new file mode 100644
567
index 0000000000..481ea8583d
568
--- /dev/null
569
+++ b/t/db_dependent/Koha/Validation.t
570
@@ -0,0 +1,76 @@
571
+#!/usr/bin/perl
572
+#
573
+# Copyright 2017 Koha-Suomi Oy
574
+#
575
+# This file is part of Koha.
576
+#
577
+# Koha is free software; you can redistribute it and/or modify it under the
578
+# terms of the GNU General Public License as published by the Free Software
579
+# Foundation; either version 3 of the License, or (at your option) any later
580
+# version.
581
+#
582
+# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
583
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
584
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
585
+#
586
+# You should have received a copy of the GNU General Public License along
587
+# with Koha; if not, write to the Free Software Foundation, Inc.,
588
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
589
+
590
+use Modern::Perl;
591
+
592
+use Test::More tests => 3;
593
+
594
+use t::lib::Mocks;
595
+
596
+BEGIN {
597
+    use_ok('Koha::Validation');
598
+}
599
+
600
+subtest 'email() tests' => sub {
601
+    plan tests => 2;
602
+
603
+    is(Koha::Validation::email('test'), 0, "'test' is invalid e-mail address'");
604
+    is(Koha::Validation::email('test@example.com'), 1, '\'test@example.com\' is '
605
+                               .'valid e-mail address');
606
+};
607
+
608
+subtest 'phone() tests' => sub {
609
+    plan tests => 3;
610
+
611
+    t::lib::Mocks::mock_preference('ValidatePhoneNumber', '');
612
+
613
+    is(Koha::Validation::phone('test'), 1, 'Phone number validation is switched '
614
+       .'off, so \'test\' is a valid phone number');
615
+
616
+    # An example: Finnish Phone number validation regex
617
+    subtest 'Finnish phone number validation regex' => sub {
618
+        t::lib::Mocks::mock_preference('ValidatePhoneNumber',
619
+            '^((90[0-9]{3})?0|\+358\s?)(?!(100|20(0|2(0|[2-3])|9[8-9])|300|600|70'
620
+           .'0|708|75(00[0-3]|(1|2)\d{2}|30[0-2]|32[0-2]|75[0-2]|98[0-2])))(4|50|'
621
+           .'10[1-9]|20(1|2(1|[4-9])|[3-9])|29|30[1-9]|71|73|75(00[3-9]|30[3-9]|3'
622
+           .'2[3-9]|53[3-9]|83[3-9])|2|3|5|6|8|9|1[3-9])\s?(\d\s?){4,19}\d$'
623
+        );
624
+
625
+        is(Koha::Validation::phone('1234'), 0, '1234 is invalid phone number.');
626
+        is(Koha::Validation::phone('+358501234567'), 1, '+358501234567 is valid '
627
+           .'phone number.');
628
+        is(Koha::Validation::phone('+1-202-555-0198'), 0, '+1-202-555-0198 is '
629
+          .'invalid phone number.');
630
+    };
631
+
632
+    subtest 'International phone number validation regex' => sub {
633
+        t::lib::Mocks::mock_preference('ValidatePhoneNumber',
634
+            '^((\+)?[1-9]{1,2})?([-\s\.])?((\(\d{1,4}\))|\d{1,4})(([-\s\.])?[0-9]'
635
+           .'{1,12}){1,2}$'
636
+        );
637
+
638
+        is(Koha::Validation::phone('nope'), 0, 'nope is invalid phone number.');
639
+        is(Koha::Validation::phone('1234'), 1, '1234 is valid phone number.');
640
+        is(Koha::Validation::phone('+358501234567'), 1, '+358501234567 is valid '
641
+           .'phone number.');
642
+        is(Koha::Validation::phone('+1-202-555-0198'), 1, '+1-202-555-0198 is '
643
+          .'valid phone number.');
644
+    };
645
+
646
+};
647
-- 
648
2.11.0
(-)a/Bug-14620-follow-up-Link-URL-in-system-preference-.patch (+23 lines)
Line 0 Link Here
1
From 820a58e04f9ee72a9c1144ad4d5191894c3f57e8 Mon Sep 17 00:00:00 2001
2
From: Katrin Fischer <katrin.fischer.83@web.de>
3
Date: Sat, 7 Oct 2017 23:40:24 +0200
4
Subject: [PATCH] Bug 14620: (follow-up) Link URL in system preference
5
 description
6
7
---
8
 koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref | 2 +-
9
 1 file changed, 1 insertion(+), 1 deletion(-)
10
11
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref
12
index 867bfe45e7..e9efda3cb4 100644
13
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref
14
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref
15
@@ -226,5 +226,5 @@ Patrons:
16
            class: code
17
          - / to validate patrons' phone numbers.
18
          - Example ^((\+)?[1-9]{1,2})?([-\s\.])?((\(\d{1,4}\))|\d{1,4})(([-\s\.])?[0-9]{1,12}){1,2}$
19
-         - (Source of example http://regexlib.com/REDetails.aspx?regexp_id=3009)
20
+         - (Source of example <a href="http://regexlib.com/REDetails.aspx?regexp_id=3009">RegExLib.com</a>)
21
          - Leave blank to accept any phone number.
22
-- 
23
2.11.0
(-)a/Bug-17499-Add-Koha-objects-for-messaging-preferenc.patch (+2422 lines)
Line 0 Link Here
1
From 5cb18bd6b778730cd86e44f2920e75b167854b3c Mon Sep 17 00:00:00 2001
2
From: Lari Taskula <lari.taskula@jns.fi>
3
Date: Fri, 21 Oct 2016 17:26:24 +0300
4
Subject: [PATCH] Bug 17499: Add Koha-objects for messaging preferences
5
6
This patch adds Koha-objects for messaging preferences.
7
8
Adds simple validation for messaging preferences.
9
10
The validation includes
11
- throw exception if both borrowernumber or categorycode is given for a new pref
12
- throw exception if patron for the given borrowernumber is not found
13
- throw exception if category for the given categorycode is not found
14
- throw exception if days in advance cannot be configured but is given
15
- throw exception if days in advance configuration is invalid (value between 0-30)
16
- throw exception if digest is not available but attempted to set on
17
- throw exception if digest must be enabled but attempted to set off
18
- throw exception on duplicate messaging preference
19
20
Adds a method for getting available messaging options.
21
22
Adds a method for setting default messaging preferenes.
23
  $patron->set_default_messaging_preferences (where $patron is a Koha::Patron)
24
  ...or...
25
  Koha::Patron::Message::Preference->new_from_default({
26
    borrowernumber => 123,
27
    categorycode => "ABC",
28
    message_attribute_id => 1,
29
  });
30
31
Since messaging preference is a feature that has multiple related database tables,
32
usage via Koha-objects is sometimes frustrating. This patch adds easy access to
33
message transport types via
34
  $preference->message_transport_types                              (for getting)
35
  $preference->set({ message_transport_types => ['email', 'sms'] }) (for setting)
36
  (also supports other calling conventions, see documentation for more)
37
38
Adds optional parameter message_name for Koha::Patron::Message::Preferences->find
39
and ->search. Simplifies the Koha-object usage by allowing developer to skip joins
40
and / or querying the message name via attribute_id from message_attributes table.
41
42
Includes test coverage for basic usage.
43
44
To test:
45
1. prove t/db_dependent/Koha/Patron/Message/*
46
47
Following Bug 17499, check also Bug 18595 that replaces C4::Members::Messaging
48
with these new Koha-objects.
49
50
Signed-off-by: Dominic Pichette <dominic@inlibro.com>
51
---
52
 Koha/Exceptions.pm                                 |   8 +-
53
 Koha/Patron.pm                                     |  42 ++
54
 Koha/Patron/Message/Attribute.pm                   |  50 ++
55
 Koha/Patron/Message/Attributes.pm                  |  55 ++
56
 Koha/Patron/Message/Preference.pm                  | 451 +++++++++++++
57
 Koha/Patron/Message/Preferences.pm                 | 146 +++++
58
 Koha/Patron/Message/Transport.pm                   |  50 ++
59
 Koha/Patron/Message/Transport/Preference.pm        |  51 ++
60
 Koha/Patron/Message/Transport/Preferences.pm       |  56 ++
61
 Koha/Patron/Message/Transport/Type.pm              |  51 ++
62
 Koha/Patron/Message/Transport/Types.pm             |  56 ++
63
 Koha/Patron/Message/Transports.pm                  |  55 ++
64
 t/db_dependent/Koha/Patron/Message/Attributes.t    |  74 +++
65
 t/db_dependent/Koha/Patron/Message/Preferences.t   | 719 +++++++++++++++++++++
66
 .../Koha/Patron/Message/Transport/Preferences.t    | 179 +++++
67
 .../Koha/Patron/Message/Transport/Types.t          |  54 ++
68
 t/db_dependent/Koha/Patron/Message/Transports.t    | 119 ++++
69
 17 files changed, 2215 insertions(+), 1 deletion(-)
70
 create mode 100644 Koha/Patron/Message/Attribute.pm
71
 create mode 100644 Koha/Patron/Message/Attributes.pm
72
 create mode 100644 Koha/Patron/Message/Preference.pm
73
 create mode 100644 Koha/Patron/Message/Preferences.pm
74
 create mode 100644 Koha/Patron/Message/Transport.pm
75
 create mode 100644 Koha/Patron/Message/Transport/Preference.pm
76
 create mode 100644 Koha/Patron/Message/Transport/Preferences.pm
77
 create mode 100644 Koha/Patron/Message/Transport/Type.pm
78
 create mode 100644 Koha/Patron/Message/Transport/Types.pm
79
 create mode 100644 Koha/Patron/Message/Transports.pm
80
 create mode 100644 t/db_dependent/Koha/Patron/Message/Attributes.t
81
 create mode 100644 t/db_dependent/Koha/Patron/Message/Preferences.t
82
 create mode 100644 t/db_dependent/Koha/Patron/Message/Transport/Preferences.t
83
 create mode 100644 t/db_dependent/Koha/Patron/Message/Transport/Types.t
84
 create mode 100644 t/db_dependent/Koha/Patron/Message/Transports.t
85
86
diff --git a/Koha/Exceptions.pm b/Koha/Exceptions.pm
87
index 528a151..c212653 100644
88
--- a/Koha/Exceptions.pm
89
+++ b/Koha/Exceptions.pm
90
@@ -27,7 +27,13 @@ use Exception::Class (
91
     },
92
     'Koha::Exceptions::MissingParameter' => {
93
         isa => 'Koha::Exceptions::Exception',
94
-        description => 'A required parameter is missing'
95
+        description => 'A required parameter is missing',
96
+        fields => ['parameter'],
97
+    },
98
+    'Koha::Exceptions::TooManyParameters' => {
99
+        isa => 'Koha::Exceptions::Exception',
100
+        description => 'Too many parameters given',
101
+        fields => ['parameter'],
102
     },
103
     'Koha::Exceptions::WrongParameter' => {
104
         isa => 'Koha::Exceptions::Exception',
105
diff --git a/Koha/Patron.pm b/Koha/Patron.pm
106
index daa972c..a00f05c 100644
107
--- a/Koha/Patron.pm
108
+++ b/Koha/Patron.pm
109
@@ -33,6 +33,7 @@ use Koha::Patron::Categories;
110
 use Koha::Patron::HouseboundProfile;
111
 use Koha::Patron::HouseboundRole;
112
 use Koha::Patron::Images;
113
+use Koha::Patron::Message::Preferences;
114
 use Koha::Patrons;
115
 use Koha::Virtualshelves;
116
 use Koha::Club::Enrollments;
117
@@ -656,6 +657,47 @@ sub account_locked {
118
           and $self->login_attempts >= $FailedLoginAttempts )? 1 : 0;
119
 }
120
 
121
+=head3 set_default_messaging_preferences
122
+
123
+    $patron->set_default_messaging_preferences
124
+
125
+Sets default messaging preferences on patron.
126
+
127
+See Koha::Patron::Message::Preference(s) for more documentation, especially on
128
+thrown exceptions.
129
+
130
+=cut
131
+
132
+sub set_default_messaging_preferences {
133
+    my ($self, $categorycode) = @_;
134
+
135
+    my $options = Koha::Patron::Message::Preferences->get_options;
136
+
137
+    foreach my $option (@$options) {
138
+        # Check that this option has preference configuration for this category
139
+        unless (Koha::Patron::Message::Preferences->search({
140
+            message_attribute_id => $option->{message_attribute_id},
141
+            categorycode         => $categorycode || $self->categorycode,
142
+        })->count) {
143
+            next;
144
+        }
145
+
146
+        # Delete current setting
147
+        Koha::Patron::Message::Preferences->search({
148
+            borrowernumber => $self->borrowernumber,
149
+             message_attribute_id => $option->{message_attribute_id},
150
+        })->delete;
151
+
152
+        Koha::Patron::Message::Preference->new_from_default({
153
+            borrowernumber => $self->borrowernumber,
154
+            categorycode   => $categorycode || $self->categorycode,
155
+            message_attribute_id => $option->{message_attribute_id},
156
+        });
157
+    }
158
+
159
+    return $self;
160
+}
161
+
162
 =head3 type
163
 
164
 =cut
165
diff --git a/Koha/Patron/Message/Attribute.pm b/Koha/Patron/Message/Attribute.pm
166
new file mode 100644
167
index 0000000..9d9004c
168
--- /dev/null
169
+++ b/Koha/Patron/Message/Attribute.pm
170
@@ -0,0 +1,50 @@
171
+package Koha::Patron::Message::Attribute;
172
+
173
+# Copyright Koha-Suomi Oy 2016
174
+#
175
+# This file is part of Koha.
176
+#
177
+# Koha is free software; you can redistribute it and/or modify it under the
178
+# terms of the GNU General Public License as published by the Free Software
179
+# Foundation; either version 3 of the License, or (at your option) any later
180
+# version.a
181
+#
182
+# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
183
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
184
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
185
+#
186
+# You should have received a copy of the GNU General Public License along
187
+# with Koha; if not, write to the Free Software Foundation, Inc.,
188
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
189
+
190
+use Modern::Perl;
191
+
192
+use Koha::Database;
193
+
194
+use base qw(Koha::Object);
195
+
196
+=head1 NAME
197
+
198
+Koha::Patron::Message::Attribute - Koha Patron Message Attribute object class
199
+
200
+=head1 API
201
+
202
+=head2 Class Methods
203
+
204
+=cut
205
+
206
+=head3 type
207
+
208
+=cut
209
+
210
+sub _type {
211
+    return 'MessageAttribute';
212
+}
213
+
214
+=head1 AUTHOR
215
+
216
+Lari Taskula <lari.taskula@jns.fi>
217
+
218
+=cut
219
+
220
+1;
221
diff --git a/Koha/Patron/Message/Attributes.pm b/Koha/Patron/Message/Attributes.pm
222
new file mode 100644
223
index 0000000..a2df4e6
224
--- /dev/null
225
+++ b/Koha/Patron/Message/Attributes.pm
226
@@ -0,0 +1,55 @@
227
+package Koha::Patron::Message::Attributes;
228
+
229
+# Copyright Koha-Suomi Oy 2016
230
+#
231
+# This file is part of Koha.
232
+#
233
+# Koha is free software; you can redistribute it and/or modify it under the
234
+# terms of the GNU General Public License as published by the Free Software
235
+# Foundation; either version 3 of the License, or (at your option) any later
236
+# version.
237
+#
238
+# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
239
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
240
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
241
+#
242
+# You should have received a copy of the GNU General Public License along
243
+# with Koha; if not, write to the Free Software Foundation, Inc.,
244
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
245
+
246
+use Modern::Perl;
247
+
248
+use Koha::Database;
249
+use Koha::Patron::Message::Attribute;
250
+
251
+use base qw(Koha::Objects);
252
+
253
+=head1 NAME
254
+
255
+Koha::Patron::Message::Attributes - Koha Patron Message Attributes object class
256
+
257
+=head1 API
258
+
259
+=head2 Class Methods
260
+
261
+=cut
262
+
263
+=head3 type
264
+
265
+=cut
266
+
267
+sub _type {
268
+    return 'MessageAttribute';
269
+}
270
+
271
+sub object_class {
272
+    return 'Koha::Patron::Message::Attribute';
273
+}
274
+
275
+=head1 AUTHOR
276
+
277
+Lari Taskula <lari.taskula@jns.fi>
278
+
279
+=cut
280
+
281
+1;
282
diff --git a/Koha/Patron/Message/Preference.pm b/Koha/Patron/Message/Preference.pm
283
new file mode 100644
284
index 0000000..db96b2a
285
--- /dev/null
286
+++ b/Koha/Patron/Message/Preference.pm
287
@@ -0,0 +1,451 @@
288
+package Koha::Patron::Message::Preference;
289
+
290
+# Copyright Koha-Suomi Oy 2016
291
+#
292
+# This file is part of Koha.
293
+#
294
+# Koha is free software; you can redistribute it and/or modify it under the
295
+# terms of the GNU General Public License as published by the Free Software
296
+# Foundation; either version 3 of the License, or (at your option) any later
297
+# version.a
298
+#
299
+# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
300
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
301
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
302
+#
303
+# You should have received a copy of the GNU General Public License along
304
+# with Koha; if not, write to the Free Software Foundation, Inc.,
305
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
306
+
307
+use Modern::Perl;
308
+
309
+use Koha::Database;
310
+use Koha::Exceptions;
311
+use Koha::Patron::Categories;
312
+use Koha::Patron::Message::Attributes;
313
+use Koha::Patron::Message::Preferences;
314
+use Koha::Patron::Message::Transport::Preferences;
315
+use Koha::Patron::Message::Transport::Types;
316
+use Koha::Patron::Message::Transports;
317
+use Koha::Patrons;
318
+
319
+use base qw(Koha::Object);
320
+
321
+=head1 NAME
322
+
323
+Koha::Patron::Message::Preference - Koha Patron Message Preference object class
324
+
325
+=head1 API
326
+
327
+=head2 Class Methods
328
+
329
+=cut
330
+
331
+=head3 new
332
+
333
+my $preference = Koha::Patron::Message::Preference->new({
334
+   borrowernumber => 123,
335
+   #categorycode => 'ABC',
336
+   message_attribute_id => 4,
337
+   message_transport_types => ['email', 'sms'], # see documentation below
338
+   wants_digest => 1,
339
+   days_in_advance => 7,
340
+});
341
+
342
+Takes either borrowernumber or categorycode, but not both.
343
+
344
+days_in_advance may not be available. See message_attributes table for takes_days
345
+configuration.
346
+
347
+wants_digest may not be available. See message_transports table for is_digest
348
+configuration.
349
+
350
+You can instantiate a new object without custom validation errors, but when
351
+storing, validation may throw exceptions. See C<validate()> for more
352
+documentation.
353
+
354
+C<message_transport_types> is a parameter that is not actually a column in this
355
+Koha-object. Given this parameter, the message transport types will be added as
356
+related transport types for this object. For get and set, you can access them via
357
+subroutine C<message_transport_types()> in this class.
358
+
359
+=cut
360
+
361
+sub new {
362
+    my ($class, $params) = @_;
363
+
364
+    my $types = $params->{'message_transport_types'};
365
+    delete $params->{'message_transport_types'};
366
+
367
+    my $self = $class->SUPER::new($params);
368
+
369
+    $self->_set_message_transport_types($types);
370
+
371
+    return $self;
372
+}
373
+
374
+=head3 new_from_default
375
+
376
+my $preference = Koha::Patron::Message::Preference->new_from_default({
377
+    borrowernumber => 123,
378
+    categorycode   => 'ABC',   # if not given, patron's categorycode will be used
379
+    message_attribute_id => 1,
380
+});
381
+
382
+NOTE: This subroutine initializes and STORES the object (in order to set
383
+message transport types for the preference), so no need to call ->store when
384
+preferences are initialized via this method.
385
+
386
+Stores default messaging preference for C<categorycode> to patron for given
387
+C<message_attribute_id>.
388
+
389
+Throws Koha::Exceptions::MissingParameter if any of following is missing:
390
+- borrowernumber
391
+- message_attribute_id
392
+
393
+Throws Koha::Exceptions::ObjectNotFound if default preferences are not found.
394
+
395
+=cut
396
+
397
+sub new_from_default {
398
+    my ($class, $params) = @_;
399
+
400
+    my @required = qw(borrowernumber message_attribute_id);
401
+    foreach my $p (@required) {
402
+        Koha::Exceptions::MissingParameter->throw(
403
+            error => 'Missing required parameter.',
404
+            parameter => $p,
405
+        ) unless exists $params->{$p};
406
+    }
407
+    unless ($params->{'categorycode'}) {
408
+        my $patron = Koha::Patrons->find($params->{borrowernumber});
409
+        $params->{'categorycode'} = $patron->categorycode;
410
+    }
411
+
412
+    my $default = Koha::Patron::Message::Preferences->find({
413
+        categorycode => $params->{'categorycode'},
414
+        message_attribute_id => $params->{'message_attribute_id'},
415
+    });
416
+    Koha::Exceptions::ObjectNotFound->throw(
417
+        error => 'Default messaging preference for given categorycode and'
418
+        .' message_attribute_id cannot be found.',
419
+    ) unless $default;
420
+    $default = $default->unblessed;
421
+
422
+    # Add a new messaging preference for patron
423
+    my $self = $class->SUPER::new({
424
+        borrowernumber => $params->{'borrowernumber'},
425
+        message_attribute_id => $default->{'message_attribute_id'},
426
+        days_in_advance => $default->{'days_in_advance'},
427
+        wants_digest => $default->{'wants_digest'},
428
+    })->store;
429
+
430
+    # Set default messaging transport types
431
+    my $default_transport_types =
432
+    Koha::Patron::Message::Transport::Preferences->search({
433
+        borrower_message_preference_id =>
434
+                    $default->{'borrower_message_preference_id'}
435
+    });
436
+    while (my $transport = $default_transport_types->next) {
437
+        Koha::Patron::Message::Transport::Preference->new({
438
+            borrower_message_preference_id => $self->borrower_message_preference_id,
439
+            message_transport_type => $transport->message_transport_type,
440
+        })->store;
441
+    }
442
+
443
+    return $self;
444
+}
445
+
446
+=head3 message_name
447
+
448
+$preference->message_name
449
+
450
+Gets message_name for this messaging preference.
451
+
452
+Setter not implemented.
453
+
454
+=cut
455
+
456
+sub message_name {
457
+    my ($self) = @_;
458
+
459
+    if ($self->{'_message_name'}) {
460
+        return $self->{'_message_name'};
461
+    }
462
+    $self->{'_message_name'} = Koha::Patron::Message::Attributes->find({
463
+        message_attribute_id => $self->message_attribute_id,
464
+    })->message_name;
465
+    return $self->{'_message_name'};
466
+}
467
+
468
+=head3 message_transport_types
469
+
470
+$preference->message_transport_types
471
+Returns a HASHREF of message transport types for this messaging preference, e.g.
472
+if ($preference->message_transport_types->{'email'}) {
473
+    # email is one of the transport preferences
474
+}
475
+
476
+$preference->message_transport_types('email', 'sms');
477
+Sets the given message transport types for this messaging preference
478
+
479
+=cut
480
+
481
+sub message_transport_types {
482
+    my $self = shift;
483
+
484
+    unless (@_) {
485
+        if ($self->{'_message_transport_types'}) {
486
+            return $self->{'_message_transport_types'};
487
+        }
488
+        map {
489
+            my $transport = Koha::Patron::Message::Transports->find({
490
+                message_attribute_id => $self->message_attribute_id,
491
+                message_transport_type => $_->message_transport_type,
492
+                is_digest => $self->wants_digest
493
+            });
494
+            unless ($transport) {
495
+                my $logger = Koha::Logger->get;
496
+                $logger->warn(
497
+                    $self->message_name . ' has no transport with '.
498
+                    $_->message_transport_type . ' (digest: '.
499
+                    ($self->wants_digest ? 'yes':'no').').'
500
+                );
501
+            }
502
+            $self->{'_message_transport_types'}->{$_->message_transport_type}
503
+                = $transport ? $transport->letter_code : ' ';
504
+        }
505
+        Koha::Patron::Message::Transport::Preferences->search({
506
+            borrower_message_preference_id => $self->borrower_message_preference_id,
507
+        })->as_list;
508
+        return $self->{'_message_transport_types'} || {};
509
+    }
510
+    else {
511
+        $self->_set_message_transport_types(@_);
512
+        return $self;
513
+    }
514
+}
515
+
516
+=head3 set
517
+
518
+$preference->set({
519
+    message_transport_types => ['sms', 'phone'],
520
+    wants_digest => 0,
521
+})->store;
522
+
523
+Sets preference object values and additionally message_transport_types if given.
524
+
525
+=cut
526
+
527
+sub set {
528
+    my ($self, $params) = @_;
529
+
530
+    my $mtt = $params->{'message_transport_types'};
531
+    delete $params->{'message_transport_types'};
532
+
533
+    $self->SUPER::set($params) if $params;
534
+    if ($mtt) {
535
+        $self->message_transport_types($mtt);
536
+    }
537
+
538
+    return $self;
539
+}
540
+
541
+=head3 store
542
+
543
+Makes a validation before actual Koha::Object->store so that proper exceptions
544
+can be thrown. See C<validate()> for documentation about exceptions.
545
+
546
+=cut
547
+
548
+sub store {
549
+    my $self = shift;
550
+
551
+    $self->validate->SUPER::store(@_);
552
+
553
+    # store message transport types
554
+    if (exists $self->{'_message_transport_types'}) {
555
+        Koha::Patron::Message::Transport::Preferences->search({
556
+            borrower_message_preference_id =>
557
+                $self->borrower_message_preference_id,
558
+        })->delete;
559
+        foreach my $type (keys %{$self->{'_message_transport_types'}}) {
560
+            Koha::Patron::Message::Transport::Preference->new({
561
+                borrower_message_preference_id =>
562
+                    $self->borrower_message_preference_id,
563
+                message_transport_type => $type,
564
+            })->store;
565
+        }
566
+    }
567
+
568
+    return $self;
569
+}
570
+
571
+=head3 validate
572
+
573
+Makes a basic validation for object.
574
+
575
+Throws following exceptions regarding parameters.
576
+- Koha::Exceptions::MissingParameter
577
+- Koha::Exceptions::TooManyParameters
578
+- Koha::Exceptions::BadParameter
579
+
580
+See $_->parameter to identify the parameter causing the exception.
581
+
582
+Throws Koha::Exceptions::DuplicateObject if this preference already exists.
583
+
584
+Returns Koha::Patron::Message::Preference object.
585
+
586
+=cut
587
+
588
+sub validate {
589
+    my ($self) = @_;
590
+
591
+    if ($self->borrowernumber && $self->categorycode) {
592
+        Koha::Exceptions::TooManyParameters->throw(
593
+            error => 'Both borrowernumber and category given, only one accepted',
594
+            parameter => ['borrowernumber', 'categorycode'],
595
+        );
596
+    }
597
+    if (!$self->borrowernumber && !$self->categorycode) {
598
+        Koha::Exceptions::MissingParameter->throw(
599
+            error => 'borrowernumber or category required, none given',
600
+            parameter => ['borrowernumber', 'categorycode'],
601
+        );
602
+    }
603
+    if ($self->borrowernumber) {
604
+        Koha::Exceptions::BadParameter->throw(
605
+            error => 'Patron not found.',
606
+            parameter => 'borrowernumber',
607
+        ) unless Koha::Patrons->find($self->borrowernumber);
608
+    }
609
+    if ($self->categorycode) {
610
+        Koha::Exceptions::BadParameter->throw(
611
+            error => 'Category not found.',
612
+            parameter => 'categorycode',
613
+        ) unless Koha::Patron::Categories->find($self->categorycode);
614
+    }
615
+
616
+    if (!$self->in_storage) {
617
+        my $previous = Koha::Patron::Message::Preferences->search({
618
+            borrowernumber => $self->borrowernumber,
619
+            categorycode   => $self->categorycode,
620
+            message_attribute_id => $self->message_attribute_id,
621
+        });
622
+        if ($previous->count) {
623
+            Koha::Exceptions::DuplicateObject->throw(
624
+                error => 'A preference for this borrower/category and'
625
+                .' message_attribute_id already exists',
626
+            );
627
+        }
628
+    }
629
+
630
+    my $attr = Koha::Patron::Message::Attributes->find(
631
+        $self->message_attribute_id
632
+    );
633
+    unless ($attr) {
634
+        Koha::Exceptions::BadParameter->throw(
635
+            error => 'Message attribute with id '.$self->message_attribute_id
636
+            .' not found',
637
+            parameter => 'message_attribute_id'
638
+        );
639
+    }
640
+    if (defined $self->days_in_advance) {
641
+        if ($attr && $attr->takes_days == 0) {
642
+            Koha::Exceptions::BadParameter->throw(
643
+                error => 'days_in_advance cannot be defined for '.
644
+                $attr->message_name . '.',
645
+                parameter => 'days_in_advance',
646
+            );
647
+        }
648
+        elsif ($self->days_in_advance < 0 || $self->days_in_advance > 30) {
649
+            Koha::Exceptions::BadParameter->throw(
650
+                error => 'days_in_advance has to be a value between 0-30 for '.
651
+                $attr->message_name . '.',
652
+                parameter => 'days_in_advance',
653
+            );
654
+        }
655
+    }
656
+    if (defined $self->wants_digest) {
657
+        my $transports = Koha::Patron::Message::Transports->search({
658
+            message_attribute_id => $self->message_attribute_id,
659
+            is_digest            => $self->wants_digest ? 1 : 0,
660
+        });
661
+        Koha::Exceptions::BadParameter->throw(
662
+            error => (!$self->wants_digest ? 'Digest must be selected'
663
+                                           : 'Digest cannot be selected')
664
+            . ' for '.$attr->message_name.'.',
665
+            parameter => 'wants_digest',
666
+        ) if $transports->count == 0;
667
+    }
668
+
669
+    return $self;
670
+}
671
+
672
+sub _set_message_transport_types {
673
+    my $self = shift;
674
+
675
+    return unless $_[0];
676
+
677
+    $self->{'_message_transport_types'} = undef;
678
+    my $types = ref $_[0] eq "ARRAY" ? $_[0] : [@_];
679
+    return unless $types;
680
+    $self->_validate_message_transport_types({ message_transport_types => $types });
681
+    foreach my $type (@$types) {
682
+        unless (exists $self->{'_message_transport_types'}->{$type}) {
683
+            my $transport = Koha::Patron::Message::Transports->find({
684
+                message_attribute_id => $self->message_attribute_id,
685
+                message_transport_type => $type
686
+            });
687
+            unless ($transport) {
688
+                Koha::Exceptions::BadParameter->throw(
689
+                    error => 'No transport configured for '.$self->message_name.
690
+                        " transport type $type.",
691
+                    parameter => 'message_transport_types'
692
+                );
693
+            }
694
+            $self->{'_message_transport_types'}->{$type}
695
+                = $transport->letter_code;
696
+        }
697
+    }
698
+    return $self;
699
+}
700
+
701
+sub _validate_message_transport_types {
702
+    my ($self, $params) = @_;
703
+
704
+    if (ref($params) eq 'HASH' && $params->{'message_transport_types'}) {
705
+        if (ref($params->{'message_transport_types'}) ne 'ARRAY') {
706
+            $params->{'message_transport_types'} = [$params->{'message_transport_types'}];
707
+        }
708
+        my $types = $params->{'message_transport_types'};
709
+
710
+        foreach my $type (@{$types}) {
711
+            unless (Koha::Patron::Message::Transport::Types->find({
712
+                message_transport_type => $type
713
+            })) {
714
+                Koha::Exceptions::BadParameter->throw(
715
+                    error => "Message transport type '$type' does not exist",
716
+                    parameter => 'message_transport_types',
717
+                );
718
+            }
719
+        }
720
+        return $types;
721
+    }
722
+}
723
+
724
+=head3 type
725
+
726
+=cut
727
+
728
+sub _type {
729
+    return 'BorrowerMessagePreference';
730
+}
731
+
732
+=head1 AUTHOR
733
+
734
+Lari Taskula <lari.taskula@jns.fi>
735
+
736
+=cut
737
+
738
+1;
739
diff --git a/Koha/Patron/Message/Preferences.pm b/Koha/Patron/Message/Preferences.pm
740
new file mode 100644
741
index 0000000..fa8e974
742
--- /dev/null
743
+++ b/Koha/Patron/Message/Preferences.pm
744
@@ -0,0 +1,146 @@
745
+package Koha::Patron::Message::Preferences;
746
+
747
+# Copyright Koha-Suomi Oy 2016
748
+#
749
+# This file is part of Koha.
750
+#
751
+# Koha is free software; you can redistribute it and/or modify it under the
752
+# terms of the GNU General Public License as published by the Free Software
753
+# Foundation; either version 3 of the License, or (at your option) any later
754
+# version.
755
+#
756
+# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
757
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
758
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
759
+#
760
+# You should have received a copy of the GNU General Public License along
761
+# with Koha; if not, write to the Free Software Foundation, Inc.,
762
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
763
+
764
+use Modern::Perl;
765
+
766
+use Koha::Database;
767
+use Koha::Patron::Message::Attributes;
768
+use Koha::Patron::Message::Preference;
769
+use Koha::Patron::Message::Transports;
770
+
771
+use base qw(Koha::Objects);
772
+
773
+=head1 NAME
774
+
775
+Koha::Patron::Message::Preferences - Koha Patron Message Preferences object class
776
+
777
+=head1 API
778
+
779
+=head2 Class Methods
780
+
781
+=cut
782
+
783
+=head3 find_with_message_name
784
+
785
+Koha::Patron::Message::Preferences->find_with_message_name({
786
+    borrowernumber => 123,
787
+    message_name => 'Hold_Filled',
788
+});
789
+
790
+Converts C<message_name> into C<message_attribute_id> and continues find.
791
+
792
+=cut
793
+
794
+sub find_with_message_name {
795
+    my ($self, $id) = @_;
796
+
797
+    if (ref($id) eq "HASH" && $id->{'message_name'}) {
798
+        my $attr = Koha::Patron::Message::Attributes->find({
799
+            message_name => $id->{'message_name'},
800
+        });
801
+        $id->{'message_attribute_id'} = ($attr) ?
802
+                    $attr->message_attribute_id : undef;
803
+        delete $id->{'message_name'};
804
+    }
805
+
806
+    return $self->SUPER::find($id);
807
+}
808
+
809
+=head3 get_options
810
+
811
+my $messaging_options = Koha::Patron::Message::Preferences->get_options
812
+
813
+Returns an ARRAYref of HASHrefs on available messaging options.
814
+
815
+=cut
816
+
817
+sub get_options {
818
+    my ($self) = @_;
819
+
820
+    my $transports = Koha::Patron::Message::Transports->search(undef,
821
+        {
822
+            join => ['message_attribute'],
823
+            '+select' => ['message_attribute.message_name', 'message_attribute.takes_days'],
824
+            '+as' => ['message_name', 'takes_days'],
825
+        });
826
+
827
+    my $choices;
828
+    while (my $transport = $transports->next) {
829
+        my $name = $transport->get_column('message_name');
830
+        $choices->{$name}->{'message_attribute_id'} = $transport->message_attribute_id;
831
+        $choices->{$name}->{'message_name'}         = $name;
832
+        $choices->{$name}->{'takes_days'}           = $transport->get_column('takes_days');
833
+        $choices->{$name}->{'has_digest'}           ||= 1 if $transport->is_digest;
834
+        $choices->{$name}->{'has_digest_off'}       ||= 1 if !$transport->is_digest;
835
+        $choices->{$name}->{'transport_'.$transport->get_column('message_transport_type')} = ' ';
836
+    }
837
+
838
+    my @return = values %$choices;
839
+    @return = sort { $a->{message_attribute_id} <=> $b->{message_attribute_id} } @return;
840
+
841
+    return \@return;
842
+}
843
+
844
+=head3 search_with_message_name
845
+
846
+Koha::Patron::Message::Preferences->search_with_message_name({
847
+    borrowernumber => 123,
848
+    message_name => 'Hold_Filled',
849
+});
850
+
851
+Converts C<message_name> into C<message_attribute_id> and continues search. Use
852
+Koha::Patron::Message::Preferences->search with a proper join for more complicated
853
+searches.
854
+
855
+=cut
856
+
857
+sub search_with_message_name {
858
+    my ($self, $params, $attributes) = @_;
859
+
860
+    if (ref($params) eq "HASH" && $params->{'message_name'}) {
861
+        my $attr = Koha::Patron::Message::Attributes->find({
862
+            message_name => $params->{'message_name'},
863
+        });
864
+        $params->{'message_attribute_id'} = ($attr) ?
865
+                    $attr->message_attribute_id : undef;
866
+        delete $params->{'message_name'};
867
+    }
868
+
869
+    return $self->SUPER::search($params, $attributes);
870
+}
871
+
872
+=head3 type
873
+
874
+=cut
875
+
876
+sub _type {
877
+    return 'BorrowerMessagePreference';
878
+}
879
+
880
+sub object_class {
881
+    return 'Koha::Patron::Message::Preference';
882
+}
883
+
884
+=head1 AUTHOR
885
+
886
+Lari Taskula <lari.taskula@jns.fi>
887
+
888
+=cut
889
+
890
+1;
891
diff --git a/Koha/Patron/Message/Transport.pm b/Koha/Patron/Message/Transport.pm
892
new file mode 100644
893
index 0000000..ca0906e
894
--- /dev/null
895
+++ b/Koha/Patron/Message/Transport.pm
896
@@ -0,0 +1,50 @@
897
+package Koha::Patron::Message::Transport;
898
+
899
+# Copyright Koha-Suomi Oy 2016
900
+#
901
+# This file is part of Koha.
902
+#
903
+# Koha is free software; you can redistribute it and/or modify it under the
904
+# terms of the GNU General Public License as published by the Free Software
905
+# Foundation; either version 3 of the License, or (at your option) any later
906
+# version.a
907
+#
908
+# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
909
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
910
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
911
+#
912
+# You should have received a copy of the GNU General Public License along
913
+# with Koha; if not, write to the Free Software Foundation, Inc.,
914
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
915
+
916
+use Modern::Perl;
917
+
918
+use Koha::Database;
919
+
920
+use base qw(Koha::Object);
921
+
922
+=head1 NAME
923
+
924
+Koha::Patron::Message::Transport - Koha Patron Message Transport object class
925
+
926
+=head1 API
927
+
928
+=head2 Class Methods
929
+
930
+=cut
931
+
932
+=head3 type
933
+
934
+=cut
935
+
936
+sub _type {
937
+    return 'MessageTransport';
938
+}
939
+
940
+=head1 AUTHOR
941
+
942
+Lari Taskula <lari.taskula@jns.fi>
943
+
944
+=cut
945
+
946
+1;
947
diff --git a/Koha/Patron/Message/Transport/Preference.pm b/Koha/Patron/Message/Transport/Preference.pm
948
new file mode 100644
949
index 0000000..fe0ddeb
950
--- /dev/null
951
+++ b/Koha/Patron/Message/Transport/Preference.pm
952
@@ -0,0 +1,51 @@
953
+package Koha::Patron::Message::Transport::Preference;
954
+
955
+# Copyright Koha-Suomi Oy 2016
956
+#
957
+# This file is part of Koha.
958
+#
959
+# Koha is free software; you can redistribute it and/or modify it under the
960
+# terms of the GNU General Public License as published by the Free Software
961
+# Foundation; either version 3 of the License, or (at your option) any later
962
+# version.a
963
+#
964
+# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
965
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
966
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
967
+#
968
+# You should have received a copy of the GNU General Public License along
969
+# with Koha; if not, write to the Free Software Foundation, Inc.,
970
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
971
+
972
+use Modern::Perl;
973
+
974
+use Koha::Database;
975
+
976
+use base qw(Koha::Object);
977
+
978
+=head1 NAME
979
+
980
+Koha::Patron::Message::Transport::Preference - Koha Patron Message Transport
981
+Preference object class
982
+
983
+=head1 API
984
+
985
+=head2 Class Methods
986
+
987
+=cut
988
+
989
+=head3 type
990
+
991
+=cut
992
+
993
+sub _type {
994
+    return 'BorrowerMessageTransportPreference';
995
+}
996
+
997
+=head1 AUTHOR
998
+
999
+Lari Taskula <lari.taskula@jns.fi>
1000
+
1001
+=cut
1002
+
1003
+1;
1004
diff --git a/Koha/Patron/Message/Transport/Preferences.pm b/Koha/Patron/Message/Transport/Preferences.pm
1005
new file mode 100644
1006
index 0000000..aabd851
1007
--- /dev/null
1008
+++ b/Koha/Patron/Message/Transport/Preferences.pm
1009
@@ -0,0 +1,56 @@
1010
+package Koha::Patron::Message::Transport::Preferences;
1011
+
1012
+# Copyright Koha-Suomi Oy 2016
1013
+#
1014
+# This file is part of Koha.
1015
+#
1016
+# Koha is free software; you can redistribute it and/or modify it under the
1017
+# terms of the GNU General Public License as published by the Free Software
1018
+# Foundation; either version 3 of the License, or (at your option) any later
1019
+# version.
1020
+#
1021
+# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
1022
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
1023
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
1024
+#
1025
+# You should have received a copy of the GNU General Public License along
1026
+# with Koha; if not, write to the Free Software Foundation, Inc.,
1027
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
1028
+
1029
+use Modern::Perl;
1030
+
1031
+use Koha::Database;
1032
+use Koha::Patron::Message::Transport::Preference;
1033
+
1034
+use base qw(Koha::Objects);
1035
+
1036
+=head1 NAME
1037
+
1038
+Koha::Patron::Message::Transport::Preferences - Koha Patron Message Transport
1039
+Preferences object class
1040
+
1041
+=head1 API
1042
+
1043
+=head2 Class Methods
1044
+
1045
+=cut
1046
+
1047
+=head3 type
1048
+
1049
+=cut
1050
+
1051
+sub _type {
1052
+    return 'BorrowerMessageTransportPreference';
1053
+}
1054
+
1055
+sub object_class {
1056
+    return 'Koha::Patron::Message::Transport::Preference';
1057
+}
1058
+
1059
+=head1 AUTHOR
1060
+
1061
+Lari Taskula <lari.taskula@jns.fi>
1062
+
1063
+=cut
1064
+
1065
+1;
1066
diff --git a/Koha/Patron/Message/Transport/Type.pm b/Koha/Patron/Message/Transport/Type.pm
1067
new file mode 100644
1068
index 0000000..4a52a10
1069
--- /dev/null
1070
+++ b/Koha/Patron/Message/Transport/Type.pm
1071
@@ -0,0 +1,51 @@
1072
+package Koha::Patron::Message::Transport::Type;
1073
+
1074
+# Copyright Koha-Suomi Oy 2016
1075
+#
1076
+# This file is part of Koha.
1077
+#
1078
+# Koha is free software; you can redistribute it and/or modify it under the
1079
+# terms of the GNU General Public License as published by the Free Software
1080
+# Foundation; either version 3 of the License, or (at your option) any later
1081
+# version.a
1082
+#
1083
+# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
1084
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
1085
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
1086
+#
1087
+# You should have received a copy of the GNU General Public License along
1088
+# with Koha; if not, write to the Free Software Foundation, Inc.,
1089
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
1090
+
1091
+use Modern::Perl;
1092
+
1093
+use Koha::Database;
1094
+
1095
+use base qw(Koha::Object);
1096
+
1097
+=head1 NAME
1098
+
1099
+Koha::Patron::Message::Transport::Type - Koha Patron Message Transport Type
1100
+object class
1101
+
1102
+=head1 API
1103
+
1104
+=head2 Class Methods
1105
+
1106
+=cut
1107
+
1108
+=head3 type
1109
+
1110
+=cut
1111
+
1112
+sub _type {
1113
+    return 'MessageTransportType';
1114
+}
1115
+
1116
+=head1 AUTHOR
1117
+
1118
+Lari Taskula <lari.taskula@jns.fi>
1119
+
1120
+=cut
1121
+
1122
+1;
1123
diff --git a/Koha/Patron/Message/Transport/Types.pm b/Koha/Patron/Message/Transport/Types.pm
1124
new file mode 100644
1125
index 0000000..2633ea3
1126
--- /dev/null
1127
+++ b/Koha/Patron/Message/Transport/Types.pm
1128
@@ -0,0 +1,56 @@
1129
+package Koha::Patron::Message::Transport::Types;
1130
+
1131
+# Copyright Koha-Suomi Oy 2016
1132
+#
1133
+# This file is part of Koha.
1134
+#
1135
+# Koha is free software; you can redistribute it and/or modify it under the
1136
+# terms of the GNU General Public License as published by the Free Software
1137
+# Foundation; either version 3 of the License, or (at your option) any later
1138
+# version.
1139
+#
1140
+# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
1141
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
1142
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
1143
+#
1144
+# You should have received a copy of the GNU General Public License along
1145
+# with Koha; if not, write to the Free Software Foundation, Inc.,
1146
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
1147
+
1148
+use Modern::Perl;
1149
+
1150
+use Koha::Database;
1151
+use Koha::Patron::Message::Transport::Type;
1152
+
1153
+use base qw(Koha::Objects);
1154
+
1155
+=head1 NAME
1156
+
1157
+Koha::Patron::Message::Transport::Types - Koha Patron Message Transport Types
1158
+object class
1159
+
1160
+=head1 API
1161
+
1162
+=head2 Class Methods
1163
+
1164
+=cut
1165
+
1166
+=head3 type
1167
+
1168
+=cut
1169
+
1170
+sub _type {
1171
+    return 'MessageTransportType';
1172
+}
1173
+
1174
+sub object_class {
1175
+    return 'Koha::Patron::Message::Transport::Type';
1176
+}
1177
+
1178
+=head1 AUTHOR
1179
+
1180
+Lari Taskula <lari.taskula@jns.fi>
1181
+
1182
+=cut
1183
+
1184
+1;
1185
diff --git a/Koha/Patron/Message/Transports.pm b/Koha/Patron/Message/Transports.pm
1186
new file mode 100644
1187
index 0000000..b6aee32
1188
--- /dev/null
1189
+++ b/Koha/Patron/Message/Transports.pm
1190
@@ -0,0 +1,55 @@
1191
+package Koha::Patron::Message::Transports;
1192
+
1193
+# Copyright Koha-Suomi Oy 2016
1194
+#
1195
+# This file is part of Koha.
1196
+#
1197
+# Koha is free software; you can redistribute it and/or modify it under the
1198
+# terms of the GNU General Public License as published by the Free Software
1199
+# Foundation; either version 3 of the License, or (at your option) any later
1200
+# version.
1201
+#
1202
+# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
1203
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
1204
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
1205
+#
1206
+# You should have received a copy of the GNU General Public License along
1207
+# with Koha; if not, write to the Free Software Foundation, Inc.,
1208
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
1209
+
1210
+use Modern::Perl;
1211
+
1212
+use Koha::Database;
1213
+use Koha::Patron::Message::Transport;
1214
+
1215
+use base qw(Koha::Objects);
1216
+
1217
+=head1 NAME
1218
+
1219
+Koha::Patron::Message::Transports - Koha Patron Message Transports object class
1220
+
1221
+=head1 API
1222
+
1223
+=head2 Class Methods
1224
+
1225
+=cut
1226
+
1227
+=head3 type
1228
+
1229
+=cut
1230
+
1231
+sub _type {
1232
+    return 'MessageTransport';
1233
+}
1234
+
1235
+sub object_class {
1236
+    return 'Koha::Patron::Message::Transport';
1237
+}
1238
+
1239
+=head1 AUTHOR
1240
+
1241
+Lari Taskula <lari.taskula@jns.fi>
1242
+
1243
+=cut
1244
+
1245
+1;
1246
diff --git a/t/db_dependent/Koha/Patron/Message/Attributes.t b/t/db_dependent/Koha/Patron/Message/Attributes.t
1247
new file mode 100644
1248
index 0000000..836b4f0
1249
--- /dev/null
1250
+++ b/t/db_dependent/Koha/Patron/Message/Attributes.t
1251
@@ -0,0 +1,74 @@
1252
+#!/usr/bin/perl
1253
+
1254
+# Copyright 2017 Koha-Suomi Oy
1255
+#
1256
+# This file is part of Koha
1257
+#
1258
+# Koha is free software; you can redistribute it and/or modify it
1259
+# under the terms of the GNU General Public License as published by
1260
+# the Free Software Foundation; either version 3 of the License, or
1261
+# (at your option) any later version.
1262
+#
1263
+# Koha is distributed in the hope that it will be useful, but
1264
+# WITHOUT ANY WARRANTY; without even the implied warranty of
1265
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1266
+# GNU General Public License for more details.
1267
+#
1268
+# You should have received a copy of the GNU General Public License
1269
+# along with Koha; if not, see <http://www.gnu.org/licenses>.
1270
+
1271
+use Modern::Perl;
1272
+
1273
+use Test::More tests => 2;
1274
+
1275
+use Koha::Database;
1276
+
1277
+my $schema  = Koha::Database->new->schema;
1278
+
1279
+subtest 'Test class imports' => sub {
1280
+    plan tests => 2;
1281
+
1282
+    use_ok('Koha::Patron::Message::Attribute');
1283
+    use_ok('Koha::Patron::Message::Attributes');
1284
+};
1285
+
1286
+subtest 'Test Koha::Patron::Message::Attributes' => sub {
1287
+    plan tests => 6;
1288
+
1289
+    $schema->storage->txn_begin;
1290
+
1291
+    Koha::Patron::Message::Attribute->new({
1292
+        message_name => 'Test_Attribute'
1293
+    })->store;
1294
+    Koha::Patron::Message::Attribute->new({
1295
+        message_name => 'Test_Attribute2',
1296
+        takes_days   => 1
1297
+    })->store;
1298
+
1299
+    my $attribute  = Koha::Patron::Message::Attributes->find({
1300
+        message_name => 'Test_Attribute' });
1301
+    my $attribute2 = Koha::Patron::Message::Attributes->find({
1302
+        message_name => 'Test_Attribute2' });
1303
+
1304
+    is($attribute->message_name, 'Test_Attribute',
1305
+       'Added a new messaging attribute.');
1306
+    is($attribute->takes_days, 0,
1307
+       'For that messaging attribute, takes_days is disabled by default.');
1308
+    is($attribute2->message_name, 'Test_Attribute2',
1309
+       'Added another messaging attribute.');
1310
+    is($attribute2->takes_days, 1,
1311
+       'takes_days is enabled for that message attribute (as expected).');
1312
+
1313
+    $attribute->delete;
1314
+    $attribute2->delete;
1315
+    is(Koha::Patron::Message::Attributes->find({
1316
+        message_name => 'Test_Attribute' }), undef,
1317
+       'Deleted the first message attribute.');
1318
+    is(Koha::Patron::Message::Attributes->find({
1319
+        message_name => 'Test_Attribute2' }), undef,
1320
+       'Deleted the second message attribute.');
1321
+
1322
+    $schema->storage->txn_rollback;
1323
+};
1324
+
1325
+1;
1326
diff --git a/t/db_dependent/Koha/Patron/Message/Preferences.t b/t/db_dependent/Koha/Patron/Message/Preferences.t
1327
new file mode 100644
1328
index 0000000..bd88c63
1329
--- /dev/null
1330
+++ b/t/db_dependent/Koha/Patron/Message/Preferences.t
1331
@@ -0,0 +1,719 @@
1332
+#!/usr/bin/perl
1333
+
1334
+# Copyright 2017 Koha-Suomi Oy
1335
+#
1336
+# This file is part of Koha
1337
+#
1338
+# Koha is free software; you can redistribute it and/or modify it
1339
+# under the terms of the GNU General Public License as published by
1340
+# the Free Software Foundation; either version 3 of the License, or
1341
+# (at your option) any later version.
1342
+#
1343
+# Koha is distributed in the hope that it will be useful, but
1344
+# WITHOUT ANY WARRANTY; without even the implied warranty of
1345
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1346
+# GNU General Public License for more details.
1347
+#
1348
+# You should have received a copy of the GNU General Public License
1349
+# along with Koha; if not, see <http://www.gnu.org/licenses>.
1350
+
1351
+use Modern::Perl;
1352
+
1353
+use Test::More tests => 7;
1354
+
1355
+use t::lib::Mocks;
1356
+use t::lib::TestBuilder;
1357
+
1358
+use C4::Context;
1359
+
1360
+use Koha::Notice::Templates;
1361
+use Koha::Patron::Categories;
1362
+use Koha::Patron::Message::Attributes;
1363
+use Koha::Patron::Message::Transport::Types;
1364
+use Koha::Patron::Message::Transports;
1365
+use Koha::Patrons;
1366
+
1367
+use File::Temp qw/tempfile/;
1368
+use Log::Log4perl;
1369
+
1370
+my $schema  = Koha::Database->new->schema;
1371
+my $builder = t::lib::TestBuilder->new;
1372
+
1373
+subtest 'Test class imports' => sub {
1374
+    plan tests => 2;
1375
+
1376
+    use_ok('Koha::Patron::Message::Preference');
1377
+    use_ok('Koha::Patron::Message::Preferences');
1378
+};
1379
+
1380
+subtest 'Test Koha::Patron::Message::Preferences' => sub {
1381
+    plan tests => 2;
1382
+
1383
+    $schema->storage->txn_begin;
1384
+
1385
+    my $attribute = build_a_test_attribute();
1386
+    my $letter = build_a_test_letter();
1387
+    my $mtt = build_a_test_transport_type();
1388
+    Koha::Patron::Message::Transport->new({
1389
+        message_attribute_id   => $attribute->message_attribute_id,
1390
+        message_transport_type => $mtt->message_transport_type,
1391
+        is_digest              => 0,
1392
+        letter_module          => $letter->module,
1393
+        letter_code            => $letter->code,
1394
+    })->store;
1395
+
1396
+    subtest 'Test for a patron' => sub {
1397
+        plan tests => 3;
1398
+
1399
+        my $patron = build_a_test_patron();
1400
+        Koha::Patron::Message::Preference->new({
1401
+            borrowernumber       => $patron->borrowernumber,
1402
+            message_attribute_id => $attribute->message_attribute_id,
1403
+            wants_digest         => 0,
1404
+            days_in_advance      => undef,
1405
+        })->store;
1406
+
1407
+        my $preference = Koha::Patron::Message::Preferences->find({
1408
+            borrowernumber       => $patron->borrowernumber,
1409
+            message_attribute_id => $attribute->message_attribute_id
1410
+        });
1411
+        ok($preference->borrower_message_preference_id > 0,
1412
+           'Added a new messaging preference for patron.');
1413
+
1414
+        subtest 'Test set not throwing an exception on duplicate object' => sub {
1415
+            plan tests => 1;
1416
+
1417
+            Koha::Patron::Message::Attributes->find({
1418
+                message_attribute_id => $attribute->message_attribute_id
1419
+            })->set({ takes_days => 1 })->store;
1420
+            $preference->set({ days_in_advance => 1 })->store;
1421
+            is(ref($preference), 'Koha::Patron::Message::Preference',
1422
+             'Updating the preference does not cause duplicate object exception');
1423
+        };
1424
+
1425
+        $preference->delete;
1426
+        is(Koha::Patron::Message::Preferences->search({
1427
+            borrowernumber       => $patron->borrowernumber,
1428
+            message_attribute_id => $attribute->message_attribute_id
1429
+        })->count, 0, 'Deleted the messaging preference.');
1430
+    };
1431
+
1432
+    subtest 'Test for a category' => sub {
1433
+        my $category = build_a_test_category();
1434
+        Koha::Patron::Message::Preference->new({
1435
+            categorycode         => $category->categorycode,
1436
+            message_attribute_id => $attribute->message_attribute_id,
1437
+            wants_digest         => 0,
1438
+            days_in_advance      => undef,
1439
+        })->store;
1440
+
1441
+        my $preference = Koha::Patron::Message::Preferences->find({
1442
+            categorycode         => $category->categorycode,
1443
+            message_attribute_id => $attribute->message_attribute_id
1444
+        });
1445
+        ok($preference->borrower_message_preference_id > 0,
1446
+           'Added a new messaging preference for category.');
1447
+
1448
+        $preference->delete;
1449
+        is(Koha::Patron::Message::Preferences->search({
1450
+            categorycode         => $category->categorycode,
1451
+            message_attribute_id => $attribute->message_attribute_id
1452
+        })->count, 0, 'Deleted the messaging preference.');
1453
+    };
1454
+
1455
+    $schema->storage->txn_rollback;
1456
+};
1457
+
1458
+subtest 'Test Koha::Patron::Message::Preferences->get_options' => sub {
1459
+    plan tests => 2;
1460
+
1461
+    subtest 'Test method availability and return value' => sub {
1462
+        plan tests => 3;
1463
+
1464
+        ok(Koha::Patron::Message::Preferences->can('get_options'),
1465
+            'Method get_options is available.');
1466
+        ok(my $options = Koha::Patron::Message::Preferences->get_options,
1467
+            'Called get_options successfully.');
1468
+        is(ref($options), 'ARRAY', 'get_options returns a ARRAYref');
1469
+    };
1470
+
1471
+    subtest 'Make sure options are correct' => sub {
1472
+        $schema->storage->txn_begin;
1473
+        my $options = Koha::Patron::Message::Preferences->get_options;
1474
+
1475
+        foreach my $option (@$options) {
1476
+            my $n = $option->{'message_name'};
1477
+            my $attr = Koha::Patron::Message::Attributes->find($option->{'message_attribute_id'});
1478
+            is($option->{'message_attribute_id'}, $attr->message_attribute_id,
1479
+               '$n: message_attribute_id is set');
1480
+            is($option->{'message_name'}, $attr->message_name, '$n: message_name is set');
1481
+            is($option->{'takes_days'}, $attr->takes_days, '$n: takes_days is set');
1482
+            my $transports = Koha::Patron::Message::Transports->search({
1483
+                message_attribute_id => $option->{'message_attribute_id'},
1484
+                is_digest => $option->{'has_digest'} || 0,
1485
+            });
1486
+            while (my $trnzport = $transports->next) {
1487
+                is($option->{'has_digest'} || 0, $trnzport->is_digest, '$n: has_digest is set for '.$trnzport->message_transport_type);
1488
+                is($option->{'transport_'.$trnzport->message_transport_type}, ' ', '$n: transport_'.$trnzport->message_transport_type.' is set');
1489
+            }
1490
+        }
1491
+
1492
+        $schema->storage->txn_rollback;
1493
+    };
1494
+};
1495
+
1496
+subtest 'Add preferences from defaults' => sub {
1497
+    plan tests => 3;
1498
+
1499
+    $schema->storage->txn_begin;
1500
+
1501
+    my $patron = build_a_test_patron();
1502
+    my ($default, $mtt1, $mtt2) = build_a_test_category_preference({
1503
+        patron => $patron,
1504
+    });
1505
+    ok(Koha::Patron::Message::Preference->new_from_default({
1506
+        borrowernumber       => $patron->borrowernumber,
1507
+        categorycode         => $patron->categorycode,
1508
+        message_attribute_id => $default->message_attribute_id,
1509
+    })->store, 'Added a default preference to patron.');
1510
+    ok(my $pref = Koha::Patron::Message::Preferences->find({
1511
+        borrowernumber       => $patron->borrowernumber,
1512
+        message_attribute_id => $default->message_attribute_id,
1513
+    }), 'Found the default preference from patron.');
1514
+    is(Koha::Patron::Message::Transport::Preferences->search({
1515
+        borrower_message_preference_id => $pref->borrower_message_preference_id
1516
+    })->count, 2, 'Found the two transport types that we set earlier');
1517
+
1518
+    $schema->storage->txn_rollback;
1519
+};
1520
+
1521
+subtest 'Test Koha::Patron::Message::Preference->message_transport_types' => sub {
1522
+    plan tests => 4;
1523
+
1524
+    ok(Koha::Patron::Message::Preference->can('message_transport_types'),
1525
+       'Method message_transport_types available');
1526
+
1527
+    subtest 'get message_transport_types' => sub {
1528
+        plan tests => 5;
1529
+
1530
+        $schema->storage->txn_begin;
1531
+
1532
+        my $patron = build_a_test_patron();
1533
+        my ($preference, $mtt1, $mtt2) = build_a_test_complete_preference({
1534
+            patron => $patron
1535
+        });
1536
+        Koha::Patron::Message::Transport::Preferences->search({
1537
+            borrower_message_preference_id => $preference->borrower_message_preference_id,
1538
+        })->delete;
1539
+        Koha::Patron::Message::Transport::Preference->new({
1540
+            borrower_message_preference_id => $preference->borrower_message_preference_id,
1541
+            message_transport_type => $mtt1->message_transport_type,
1542
+        })->store;
1543
+        Koha::Patron::Message::Transport::Preference->new({
1544
+            borrower_message_preference_id => $preference->borrower_message_preference_id,
1545
+            message_transport_type => $mtt2->message_transport_type,
1546
+        })->store;
1547
+        my $stored_transports = Koha::Patron::Message::Transport::Preferences->search({
1548
+            borrower_message_preference_id => $preference->borrower_message_preference_id,
1549
+        });
1550
+        my $transport1 = Koha::Patron::Message::Transports->find({
1551
+            message_attribute_id => $preference->message_attribute_id,
1552
+            message_transport_type => $mtt1->message_transport_type,
1553
+        });
1554
+        my $transport2 = Koha::Patron::Message::Transports->find({
1555
+            message_attribute_id => $preference->message_attribute_id,
1556
+            message_transport_type => $mtt2->message_transport_type,
1557
+        });
1558
+        my $transports = $preference->message_transport_types;
1559
+        is(keys %{$transports}, $stored_transports->count,
1560
+           '->message_transport_types gets correct amount of transport types.');
1561
+        is($transports->{$stored_transports->next->message_transport_type},
1562
+           $transport1->letter_code, 'Found correct message transport type and letter code.');
1563
+        is($transports->{$stored_transports->next->message_transport_type},
1564
+           $transport2->letter_code, 'Found correct message transport type and letter code.');
1565
+        ok(!$preference->message_transport_types->{'nonexistent'},
1566
+           'Didn\'t find nonexistent transport type.');
1567
+
1568
+        subtest 'test logging of warnings by invalid message transport type' => sub {
1569
+            plan tests => 2;
1570
+
1571
+            my $log = mytempfile();
1572
+            my $conf = mytempfile( <<"HERE"
1573
+log4perl.logger.opac = WARN, OPAC
1574
+log4perl.appender.OPAC=Log::Log4perl::Appender::TestBuffer
1575
+log4perl.appender.OPAC.filename=$log
1576
+log4perl.appender.OPAC.mode=append
1577
+log4perl.appender.OPAC.layout=SimpleLayout
1578
+log4perl.logger.intranet = WARN, INTRANET
1579
+log4perl.appender.INTRANET=Log::Log4perl::Appender::TestBuffer
1580
+log4perl.appender.INTRANET.filename=$log
1581
+log4perl.appender.INTRANET.mode=append
1582
+log4perl.appender.INTRANET.layout=SimpleLayout
1583
+HERE
1584
+            );
1585
+            t::lib::Mocks::mock_config('log4perl_conf', $conf);
1586
+            my $appenders = Log::Log4perl->appenders;
1587
+            my $appender = Log::Log4perl->appenders->{OPAC};
1588
+
1589
+            my $pref = Koha::Patron::Message::Preferences->find(
1590
+                $preference->borrower_message_preference_id
1591
+            );
1592
+            my $transports = $pref->message_transport_types;
1593
+            is($appender, undef, 'Nothing in buffer yet');
1594
+
1595
+            my $mtt_new = build_a_test_transport_type();
1596
+            Koha::Patron::Message::Transport::Preference->new({
1597
+                borrower_message_preference_id =>
1598
+                                $pref->borrower_message_preference_id,
1599
+                message_transport_type => $mtt_new->message_transport_type,
1600
+            })->store;
1601
+            $pref = Koha::Patron::Message::Preferences->find(
1602
+                $pref->borrower_message_preference_id
1603
+            );
1604
+            $transports = $pref->message_transport_types;
1605
+            $appender = Log::Log4perl->appenders->{OPAC};
1606
+            my $name = $pref->message_name;
1607
+            my $tt = $mtt_new->message_transport_type;
1608
+            like($appender->buffer, qr/WARN - $name has no transport with $tt/,
1609
+                 'Logged invalid message transport type');
1610
+        };
1611
+
1612
+        $schema->storage->txn_rollback;
1613
+    };
1614
+
1615
+    subtest 'set message_transport_types' => sub {
1616
+        plan tests => 6;
1617
+
1618
+        $schema->storage->txn_begin;
1619
+
1620
+        my $patron = build_a_test_patron();
1621
+        my ($preference, $mtt1, $mtt2) = build_a_test_complete_preference({
1622
+            patron => $patron
1623
+        });
1624
+
1625
+        my $mtt1_str = $mtt1->message_transport_type;
1626
+        my $mtt2_str = $mtt2->message_transport_type;
1627
+        # 1/3, use message_transport_types(list)
1628
+        Koha::Patron::Message::Transport::Preferences->search({
1629
+            borrower_message_preference_id => $preference->borrower_message_preference_id,
1630
+        })->delete;
1631
+        ok($preference->message_transport_types($mtt1_str, $mtt2_str)->store,
1632
+           '1/3 Set returned true.');
1633
+        my $stored_transports = Koha::Patron::Message::Transport::Preferences->search({
1634
+            borrower_message_preference_id => $preference->borrower_message_preference_id,
1635
+            '-or' => [
1636
+                message_transport_type => $mtt1_str,
1637
+                message_transport_type => $mtt2_str
1638
+            ]
1639
+        });
1640
+        is($stored_transports->count, 2, 'Two transports selected');
1641
+
1642
+        # 2/3, use message_transport_types(ARRAYREF)
1643
+        Koha::Patron::Message::Transport::Preferences->search({
1644
+            borrower_message_preference_id => $preference->borrower_message_preference_id,
1645
+        })->delete;
1646
+        ok($preference->message_transport_types([$mtt1_str, $mtt2_str])->store,
1647
+           '2/3 Set returned true.');
1648
+        $stored_transports = Koha::Patron::Message::Transport::Preferences->search({
1649
+            borrower_message_preference_id => $preference->borrower_message_preference_id,
1650
+            '-or' => [
1651
+                message_transport_type => $mtt1_str,
1652
+                message_transport_type => $mtt2_str
1653
+            ]
1654
+        });
1655
+        is($stored_transports->count, 2, 'Two transports selected');
1656
+
1657
+        # 3/3, use set({ message_transport_types => ARRAYREF })
1658
+        Koha::Patron::Message::Transport::Preferences->search({
1659
+            borrower_message_preference_id => $preference->borrower_message_preference_id,
1660
+        })->delete;
1661
+        ok($preference->set({
1662
+            message_transport_types => [$mtt1_str, $mtt2_str]})->store,
1663
+           '3/3 Set returned true.');
1664
+        $stored_transports = Koha::Patron::Message::Transport::Preferences->search({
1665
+            borrower_message_preference_id => $preference->borrower_message_preference_id,
1666
+            '-or' => [
1667
+                message_transport_type => $mtt1_str,
1668
+                message_transport_type => $mtt2_str
1669
+            ]
1670
+        });
1671
+        is($stored_transports->count, 2, 'Two transports selected');
1672
+
1673
+        $schema->storage->txn_rollback;
1674
+    };
1675
+
1676
+    subtest 'new message_transport_types' => sub {
1677
+        plan tests => 3;
1678
+
1679
+        $schema->storage->txn_begin;
1680
+
1681
+        my $patron    = build_a_test_patron();
1682
+        my $letter    = build_a_test_letter();
1683
+        my $attribute = build_a_test_attribute();
1684
+        my $mtt       = build_a_test_transport_type();
1685
+        Koha::Patron::Message::Transport->new({
1686
+            message_attribute_id   => $attribute->message_attribute_id,
1687
+            message_transport_type => $mtt->message_transport_type,
1688
+            is_digest              => 0,
1689
+            letter_module          => $letter->module,
1690
+            letter_code            => $letter->code,
1691
+        })->store;
1692
+        ok(my $preference = Koha::Patron::Message::Preference->new({
1693
+            borrowernumber => $patron->borrowernumber,
1694
+            message_attribute_id => $attribute->message_attribute_id,
1695
+            wants_digest => 0,
1696
+            days_in_advance => undef,
1697
+            message_transport_types => $mtt->message_transport_type,
1698
+        })->store, 'Added a new messaging preference and transport types to patron.');
1699
+        ok($preference->message_transport_types->{$mtt->message_transport_type},
1700
+           'The transport type is stored in the object.');
1701
+        my $stored_transports = Koha::Patron::Message::Transport::Preferences->search({
1702
+            borrower_message_preference_id => $preference->borrower_message_preference_id,
1703
+        });
1704
+        is($stored_transports->next->message_transport_type, $mtt->message_transport_type,
1705
+           'The transport type is stored in the database.');
1706
+
1707
+        $schema->storage->txn_rollback;
1708
+    };
1709
+};
1710
+
1711
+subtest 'Test Koha::Patron::Message::Preference->message_name' => sub {
1712
+    plan tests => 1;
1713
+
1714
+    $schema->storage->txn_begin;
1715
+
1716
+    my $patron      = build_a_test_patron();
1717
+    my $attribute   = build_a_test_attribute();
1718
+    my ($preference, $mtt1, $mtt2) = build_a_test_complete_preference({
1719
+        patron => $patron,
1720
+        attr   => $attribute,
1721
+    });
1722
+    my $message_name_pref = Koha::Patron::Message::Preferences->search_with_message_name({
1723
+        borrowernumber => $patron->{'borrowernumber'},
1724
+        message_name => $attribute->message_name,
1725
+    })->next;
1726
+    is($message_name_pref->message_name, $attribute->message_name, "Found preference with message_name");
1727
+
1728
+    $schema->storage->txn_rollback;
1729
+};
1730
+
1731
+subtest 'Test adding a new preference with invalid parameters' => sub {
1732
+    plan tests => 4;
1733
+
1734
+    subtest 'Missing parameters' => sub {
1735
+        plan tests => 1;
1736
+
1737
+        eval { Koha::Patron::Message::Preference->new->store };
1738
+        is(ref $@, 'Koha::Exceptions::MissingParameter',
1739
+            'Adding a message preference without parameters'
1740
+            .' => Koha::Exceptions::MissingParameter');
1741
+    };
1742
+
1743
+    subtest 'Too many parameters' => sub {
1744
+        plan tests => 1;
1745
+
1746
+        $schema->storage->txn_begin;
1747
+
1748
+        my $patron = build_a_test_patron();
1749
+        eval { Koha::Patron::Message::Preference->new({
1750
+            borrowernumber => $patron->borrowernumber,
1751
+            categorycode   => $patron->categorycode,
1752
+        })->store };
1753
+        is(ref $@, 'Koha::Exceptions::TooManyParameters',
1754
+            'Adding a message preference for both borrowernumber and categorycode'
1755
+            .' => Koha::Exceptions::TooManyParameters');
1756
+
1757
+        $schema->storage->txn_rollback;
1758
+    };
1759
+
1760
+    subtest 'Bad parameter' => sub {
1761
+        plan tests => 22;
1762
+
1763
+        $schema->storage->txn_begin;
1764
+
1765
+        eval { Koha::Patron::Message::Preference->new({
1766
+                borrowernumber => -999,
1767
+            })->store };
1768
+        is(ref $@, 'Koha::Exceptions::BadParameter',
1769
+            'Adding a message preference with invalid borrowernumber'
1770
+            .' => Koha::Exceptions::BadParameter');
1771
+        is ($@->parameter, 'borrowernumber', 'The previous exception tells us it'
1772
+            .' was the borrowernumber.');
1773
+
1774
+        eval { Koha::Patron::Message::Preference->new({
1775
+                categorycode => 'nonexistent',
1776
+            })->store };
1777
+        is(ref $@, 'Koha::Exceptions::BadParameter',
1778
+            'Adding a message preference with invalid categorycode'
1779
+            .' => Koha::Exceptions::BadParameter');
1780
+        is($@->parameter, 'categorycode', 'The previous exception tells us it'
1781
+            .' was the categorycode.');
1782
+
1783
+        my $attribute = build_a_test_attribute({ takes_days => 0 });
1784
+        my $patron    = build_a_test_patron();
1785
+        eval { Koha::Patron::Message::Preference->new({
1786
+                borrowernumber => $patron->borrowernumber,
1787
+                message_attribute_id => $attribute->message_attribute_id,
1788
+                days_in_advance => 10,
1789
+            })->store };
1790
+        is(ref $@, 'Koha::Exceptions::BadParameter',
1791
+            'Adding a message preference with days in advance option when not'
1792
+            .' available => Koha::Exceptions::BadParameter');
1793
+        is($@->parameter, 'days_in_advance', 'The previous exception tells us it'
1794
+            .' was the days_in_advance.');
1795
+
1796
+        $attribute->set({ takes_days => 1 })->store;
1797
+        eval { Koha::Patron::Message::Preference->new({
1798
+                borrowernumber => $patron->borrowernumber,
1799
+                message_attribute_id => $attribute->message_attribute_id,
1800
+                days_in_advance => 31,
1801
+            })->store };
1802
+        is(ref $@, 'Koha::Exceptions::BadParameter',
1803
+            'Adding a message preference with days in advance option too large'
1804
+            .' => Koha::Exceptions::BadParameter');
1805
+        is($@->parameter, 'days_in_advance', 'The previous exception tells us it'
1806
+            .' was the days_in_advance.');
1807
+
1808
+        eval { Koha::Patron::Message::Preference->new({
1809
+                borrowernumber => $patron->borrowernumber,
1810
+                message_transport_types => ['nonexistent']
1811
+            })->store };
1812
+        is (ref $@, 'Koha::Exceptions::BadParameter',
1813
+            'Adding a message preference with invalid message_transport_type'
1814
+            .' => Koha::Exceptions::BadParameter');
1815
+        is ($@->parameter, 'message_transport_types', 'The previous exception '
1816
+            .'tells us it was the message_transport_types.');
1817
+
1818
+        my $mtt_new = build_a_test_transport_type();
1819
+        eval {
1820
+            Koha::Patron::Message::Preference->new({
1821
+                borrowernumber => $patron->borrowernumber,
1822
+                message_attribute_id => $attribute->message_attribute_id,
1823
+                message_transport_types => [$mtt_new->message_transport_type],
1824
+                wants_digest => 1,
1825
+            })->store };
1826
+        is (ref $@, 'Koha::Exceptions::BadParameter',
1827
+            'Adding a message preference with invalid message_transport_type'
1828
+           .' => Koha::Exceptions::BadParameter');
1829
+        is ($@->parameter, 'message_transport_types', 'The previous exception '
1830
+            .'tells us it was the message_transport_types.');
1831
+        like ($@->error, qr/^No transport configured/, 'Exception is because of '
1832
+            .'given message_transport_type is not a valid option.');
1833
+
1834
+        eval {
1835
+            Koha::Patron::Message::Preference->new({
1836
+                borrowernumber => $patron->borrowernumber,
1837
+                message_attribute_id => $attribute->message_attribute_id,
1838
+                message_transport_types => [],
1839
+                wants_digest => 1,
1840
+            })->store };
1841
+        is (ref $@, 'Koha::Exceptions::BadParameter',
1842
+            'Adding a message preference with invalid message_transport_type'
1843
+            .' => Koha::Exceptions::BadParameter');
1844
+        is ($@->parameter, 'wants_digest', 'The previous exception tells us it'
1845
+            .' was the wants_digest');
1846
+        like ($@->error, qr/^Digest cannot be selected/, 'Exception s because of'
1847
+            .' given digest is not available for this transport.');
1848
+
1849
+        eval {
1850
+            Koha::Patron::Message::Preference->new({
1851
+                borrowernumber => $patron->borrowernumber,
1852
+                message_attribute_id => $attribute->message_attribute_id,
1853
+                message_transport_types => [],
1854
+                wants_digest => 0,
1855
+            })->store };
1856
+        is (ref $@, 'Koha::Exceptions::BadParameter',
1857
+            'Adding a message preference with invalid message_transport_type'
1858
+            .' => Koha::Exceptions::BadParameter');
1859
+        is ($@->parameter, 'wants_digest', 'The previous exception tells us it'
1860
+            .' was the wants_digest');
1861
+        like ($@->error, qr/^Digest must be selected/, 'Exception s because of'
1862
+            .' digest has to be on for this transport.');
1863
+
1864
+        eval {
1865
+            Koha::Patron::Message::Preference->new({
1866
+                borrowernumber => $patron->borrowernumber,
1867
+                message_attribute_id => -1,
1868
+                message_transport_types => [],
1869
+            })->store };
1870
+        is (ref $@, 'Koha::Exceptions::BadParameter',
1871
+            'Adding a message preference with invalid message_transport_type'
1872
+            .' => Koha::Exceptions::BadParameter');
1873
+        is ($@->parameter, 'message_attribute_id', 'The previous exception tells'
1874
+            .' us it was the message_attribute_id');
1875
+        like ($@->error, qr/^Message attribute with id -1 not found/, 'Exception '
1876
+            .' is because of given message attribute id is not found.');
1877
+
1878
+        $schema->storage->txn_rollback;
1879
+    };
1880
+
1881
+    subtest 'Duplicate object' => sub {
1882
+        plan tests => 2;
1883
+
1884
+        $schema->storage->txn_begin;
1885
+
1886
+        my $attribute = build_a_test_attribute();
1887
+        my $letter = build_a_test_letter();
1888
+        my $mtt = build_a_test_transport_type();
1889
+        Koha::Patron::Message::Transport->new({
1890
+            message_attribute_id   => $attribute->message_attribute_id,
1891
+            message_transport_type => $mtt->message_transport_type,
1892
+            is_digest              => 0,
1893
+            letter_module          => $letter->module,
1894
+            letter_code            => $letter->code,
1895
+        })->store;
1896
+        my $patron    = build_a_test_patron();
1897
+        my $preference = Koha::Patron::Message::Preference->new({
1898
+            borrowernumber => $patron->borrowernumber,
1899
+            message_attribute_id => $attribute->message_attribute_id,
1900
+            wants_digest => 0,
1901
+            days_in_advance => undef,
1902
+        })->store;
1903
+        ok($preference->borrower_message_preference_id,
1904
+           'Added a new messaging preference for patron.');
1905
+        eval { Koha::Patron::Message::Preference->new({
1906
+            borrowernumber => $patron->borrowernumber,
1907
+            message_attribute_id => $attribute->message_attribute_id,
1908
+            wants_digest => 0,
1909
+            days_in_advance => undef,
1910
+        })->store };
1911
+        is(ref $@, 'Koha::Exceptions::DuplicateObject',
1912
+                'Adding a duplicate preference'
1913
+                .' => Koha::Exceptions::DuplicateObject');
1914
+
1915
+        $schema->storage->txn_rollback;
1916
+    };
1917
+};
1918
+
1919
+sub build_a_test_attribute {
1920
+    my ($params) = @_;
1921
+
1922
+    $params->{takes_days} = $params->{takes_days} && $params->{takes_days} > 0
1923
+                            ? 1 : 0;
1924
+
1925
+    my $attribute = $builder->build({
1926
+        source => 'MessageAttribute',
1927
+        value => $params,
1928
+    });
1929
+
1930
+    return Koha::Patron::Message::Attributes->find(
1931
+        $attribute->{message_attribute_id}
1932
+    );
1933
+}
1934
+
1935
+sub build_a_test_category {
1936
+    my $categorycode   = $builder->build({
1937
+        source => 'Category' })->{categorycode};
1938
+
1939
+    return Koha::Patron::Categories->find($categorycode);
1940
+}
1941
+
1942
+sub build_a_test_letter {
1943
+    my ($params) = @_;
1944
+
1945
+    my $mtt = $params->{mtt} ? $params->{mtt} : 'email';
1946
+    my $branchcode     = $builder->build({
1947
+        source => 'Branch' })->{branchcode};
1948
+    my $letter = $builder->build({
1949
+        source => 'Letter',
1950
+        value => {
1951
+            branchcode => '',
1952
+            is_html => 0,
1953
+            message_transport_type => $mtt
1954
+        }
1955
+    });
1956
+
1957
+    return Koha::Notice::Templates->find({
1958
+        module     => $letter->{module},
1959
+        code       => $letter->{code},
1960
+        branchcode => $letter->{branchcode},
1961
+    });
1962
+}
1963
+
1964
+sub build_a_test_patron {
1965
+    my $categorycode   = $builder->build({
1966
+        source => 'Category' })->{categorycode};
1967
+    my $branchcode     = $builder->build({
1968
+        source => 'Branch' })->{branchcode};
1969
+    my $borrowernumber = $builder->build({
1970
+        source => 'Borrower' })->{borrowernumber};
1971
+
1972
+    return Koha::Patrons->find($borrowernumber);
1973
+}
1974
+
1975
+sub build_a_test_transport_type {
1976
+    my $mtt = $builder->build({
1977
+        source => 'MessageTransportType' });
1978
+
1979
+    return Koha::Patron::Message::Transport::Types->find(
1980
+        $mtt->{message_transport_type}
1981
+    );
1982
+}
1983
+
1984
+sub build_a_test_category_preference {
1985
+    my ($params) = @_;
1986
+
1987
+    my $patron = $params->{patron};
1988
+    my $attr = $params->{attr}
1989
+                    ? $params->{attr}
1990
+                    : build_a_test_attribute($params->{days_in_advance});
1991
+
1992
+    my $letter = $params->{letter} ? $params->{letter} : build_a_test_letter();
1993
+    my $mtt1 = $params->{mtt1} ? $params->{mtt1} : build_a_test_transport_type();
1994
+    my $mtt2 = $params->{mtt2} ? $params->{mtt2} : build_a_test_transport_type();
1995
+
1996
+    Koha::Patron::Message::Transport->new({
1997
+        message_attribute_id   => $attr->message_attribute_id,
1998
+        message_transport_type => $mtt1->message_transport_type,
1999
+        is_digest              => $params->{digest} ? 1 : 0,
2000
+        letter_module          => $letter->module,
2001
+        letter_code            => $letter->code,
2002
+    })->store;
2003
+
2004
+    Koha::Patron::Message::Transport->new({
2005
+        message_attribute_id   => $attr->message_attribute_id,
2006
+        message_transport_type => $mtt2->message_transport_type,
2007
+        is_digest              => $params->{digest} ? 1 : 0,
2008
+        letter_module          => $letter->module,
2009
+        letter_code            => $letter->code,
2010
+    })->store;
2011
+
2012
+    my $default = Koha::Patron::Message::Preference->new({
2013
+        categorycode         => $patron->categorycode,
2014
+        message_attribute_id => $attr->message_attribute_id,
2015
+        wants_digest         => $params->{digest} ? 1 : 0,
2016
+        days_in_advance      => $params->{days_in_advance}
2017
+                                 ? $params->{days_in_advance} : undef,
2018
+    })->store;
2019
+
2020
+    Koha::Patron::Message::Transport::Preference->new({
2021
+        borrower_message_preference_id => $default->borrower_message_preference_id,
2022
+        message_transport_type         => $mtt1->message_transport_type,
2023
+    })->store;
2024
+    Koha::Patron::Message::Transport::Preference->new({
2025
+        borrower_message_preference_id => $default->borrower_message_preference_id,
2026
+        message_transport_type         => $mtt2->message_transport_type,
2027
+    })->store;
2028
+
2029
+    return ($default, $mtt1, $mtt2);
2030
+}
2031
+
2032
+sub build_a_test_complete_preference {
2033
+    my ($params) = @_;
2034
+
2035
+    my ($default, $mtt1, $mtt2) = build_a_test_category_preference($params);
2036
+    my $patron = $params->{patron};
2037
+    $patron->set_default_messaging_preferences;
2038
+    return (Koha::Patron::Message::Preferences->search({
2039
+        borrowernumber => $patron->borrowernumber
2040
+    })->next, $mtt1, $mtt2);
2041
+}
2042
+
2043
+sub mytempfile {
2044
+    my ( $fh, $fn ) = tempfile( SUFFIX => '.logger.test', UNLINK => 1 );
2045
+    print $fh $_[0]//'';
2046
+    close $fh;
2047
+    return $fn;
2048
+}
2049
+
2050
+1;
2051
diff --git a/t/db_dependent/Koha/Patron/Message/Transport/Preferences.t b/t/db_dependent/Koha/Patron/Message/Transport/Preferences.t
2052
new file mode 100644
2053
index 0000000..0cdf809
2054
--- /dev/null
2055
+++ b/t/db_dependent/Koha/Patron/Message/Transport/Preferences.t
2056
@@ -0,0 +1,179 @@
2057
+#!/usr/bin/perl
2058
+
2059
+# Copyright 2017 Koha-Suomi Oy
2060
+#
2061
+# This file is part of Koha
2062
+#
2063
+# Koha is free software; you can redistribute it and/or modify it
2064
+# under the terms of the GNU General Public License as published by
2065
+# the Free Software Foundation; either version 3 of the License, or
2066
+# (at your option) any later version.
2067
+#
2068
+# Koha is distributed in the hope that it will be useful, but
2069
+# WITHOUT ANY WARRANTY; without even the implied warranty of
2070
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2071
+# GNU General Public License for more details.
2072
+#
2073
+# You should have received a copy of the GNU General Public License
2074
+# along with Koha; if not, see <http://www.gnu.org/licenses>.
2075
+
2076
+use Modern::Perl;
2077
+
2078
+use Test::More tests => 2;
2079
+
2080
+use t::lib::Mocks;
2081
+use t::lib::TestBuilder;
2082
+
2083
+use Koha::Notice::Templates;
2084
+use Koha::Patron::Categories;
2085
+use Koha::Patron::Message::Attributes;
2086
+use Koha::Patron::Message::Preferences;
2087
+use Koha::Patron::Message::Transport::Types;
2088
+use Koha::Patron::Message::Transports;
2089
+use Koha::Patrons;
2090
+
2091
+my $schema  = Koha::Database->new->schema;
2092
+my $builder = t::lib::TestBuilder->new;
2093
+
2094
+subtest 'Test class imports' => sub {
2095
+    plan tests => 2;
2096
+
2097
+    use_ok('Koha::Patron::Message::Transport::Preference');
2098
+    use_ok('Koha::Patron::Message::Transport::Preferences');
2099
+};
2100
+
2101
+subtest 'Test Koha::Patron::Message::Transport::Preferences' => sub {
2102
+    plan tests => 2;
2103
+
2104
+    $schema->storage->txn_begin;
2105
+
2106
+    my $attribute = build_a_test_attribute();
2107
+    my $mtt       = build_a_test_transport_type();
2108
+    my $letter    = build_a_test_letter({
2109
+        mtt => $mtt->message_transport_type
2110
+    });
2111
+    Koha::Patron::Message::Transport->new({
2112
+        message_attribute_id   => $attribute->message_attribute_id,
2113
+        message_transport_type => $mtt->message_transport_type,
2114
+        is_digest              => 0,
2115
+        letter_module          => $letter->module,
2116
+        letter_code            => $letter->code,
2117
+    })->store;
2118
+
2119
+    subtest 'For a patron' => sub {
2120
+        my $patron    = build_a_test_patron();
2121
+        my $preference = Koha::Patron::Message::Preference->new({
2122
+            borrowernumber       => $patron->borrowernumber,
2123
+            message_attribute_id => $attribute->message_attribute_id,
2124
+            wants_digest         => 0,
2125
+            days_in_advance      => undef,
2126
+        })->store;
2127
+
2128
+        my $pref_id = $preference->borrower_message_preference_id;
2129
+        my $transport_pref = Koha::Patron::Message::Transport::Preference->new({
2130
+            borrower_message_preference_id => $pref_id,
2131
+            message_transport_type => $mtt->message_transport_type,
2132
+        })->store;
2133
+        is(ref($transport_pref), 'Koha::Patron::Message::Transport::Preference',
2134
+           'Added a new messaging transport preference for patron.');
2135
+
2136
+        $transport_pref->delete;
2137
+        is(Koha::Patron::Message::Transport::Preferences->search({
2138
+            borrower_message_preference_id => $pref_id,
2139
+            message_transport_type => $mtt->message_transport_type,
2140
+        })->count, 0, 'Deleted the messaging transport preference.');
2141
+    };
2142
+
2143
+    subtest 'For a category' => sub {
2144
+        my $category   = build_a_test_category();
2145
+        my $preference = Koha::Patron::Message::Preference->new({
2146
+            categorycode         => $category->categorycode,
2147
+            message_attribute_id => $attribute->message_attribute_id,
2148
+            wants_digest         => 0,
2149
+            days_in_advance      => undef,
2150
+        })->store;
2151
+
2152
+        my $pref_id = $preference->borrower_message_preference_id;
2153
+        my $transport_pref = Koha::Patron::Message::Transport::Preference->new({
2154
+            borrower_message_preference_id => $pref_id,
2155
+            message_transport_type => $mtt->message_transport_type,
2156
+        })->store;
2157
+        is(ref($transport_pref), 'Koha::Patron::Message::Transport::Preference',
2158
+           'Added a new messaging transport preference for category.');
2159
+
2160
+        $transport_pref->delete;
2161
+        is(Koha::Patron::Message::Transport::Preferences->search({
2162
+            borrower_message_preference_id => $pref_id,
2163
+            message_transport_type => $mtt->message_transport_type,
2164
+        })->count, 0, 'Deleted the messaging transport preference.');
2165
+    };
2166
+
2167
+    $schema->storage->txn_rollback;
2168
+};
2169
+
2170
+sub build_a_test_attribute {
2171
+    my ($params) = @_;
2172
+
2173
+    $params->{takes_days} = $params->{takes_days} && $params->{takes_days} > 0
2174
+                            ? 1 : 0;
2175
+
2176
+    my $attribute = $builder->build({
2177
+        source => 'MessageAttribute',
2178
+        value => $params,
2179
+    });
2180
+
2181
+    return Koha::Patron::Message::Attributes->find(
2182
+        $attribute->{message_attribute_id}
2183
+    );
2184
+}
2185
+
2186
+sub build_a_test_category {
2187
+    my $categorycode   = $builder->build({
2188
+        source => 'Category' })->{categorycode};
2189
+
2190
+    return Koha::Patron::Categories->find($categorycode);
2191
+}
2192
+
2193
+sub build_a_test_letter {
2194
+    my ($params) = @_;
2195
+
2196
+    my $mtt = $params->{mtt} ? $params->{mtt} : 'email';
2197
+    my $branchcode     = $builder->build({
2198
+        source => 'Branch' })->{branchcode};
2199
+    my $letter = $builder->build({
2200
+        source => 'Letter',
2201
+        value => {
2202
+            branchcode => '',
2203
+            is_html => 0,
2204
+            message_transport_type => $mtt
2205
+        }
2206
+    });
2207
+
2208
+    return Koha::Notice::Templates->find({
2209
+        module => $letter->{module},
2210
+        code   => $letter->{code},
2211
+        branchcode => $letter->{branchcode},
2212
+    });
2213
+}
2214
+
2215
+sub build_a_test_patron {
2216
+    my $categorycode   = $builder->build({
2217
+        source => 'Category' })->{categorycode};
2218
+    my $branchcode     = $builder->build({
2219
+        source => 'Branch' })->{branchcode};
2220
+    my $borrowernumber = $builder->build({
2221
+        source => 'Borrower' })->{borrowernumber};
2222
+
2223
+    return Koha::Patrons->find($borrowernumber);
2224
+}
2225
+
2226
+sub build_a_test_transport_type {
2227
+    my $mtt = $builder->build({
2228
+        source => 'MessageTransportType' });
2229
+
2230
+    return Koha::Patron::Message::Transport::Types->find(
2231
+        $mtt->{message_transport_type}
2232
+    );
2233
+}
2234
+
2235
+1;
2236
diff --git a/t/db_dependent/Koha/Patron/Message/Transport/Types.t b/t/db_dependent/Koha/Patron/Message/Transport/Types.t
2237
new file mode 100644
2238
index 0000000..cbba32b
2239
--- /dev/null
2240
+++ b/t/db_dependent/Koha/Patron/Message/Transport/Types.t
2241
@@ -0,0 +1,54 @@
2242
+#!/usr/bin/perl
2243
+
2244
+# Copyright 2017 Koha-Suomi Oy
2245
+#
2246
+# This file is part of Koha
2247
+#
2248
+# Koha is free software; you can redistribute it and/or modify it
2249
+# under the terms of the GNU General Public License as published by
2250
+# the Free Software Foundation; either version 3 of the License, or
2251
+# (at your option) any later version.
2252
+#
2253
+# Koha is distributed in the hope that it will be useful, but
2254
+# WITHOUT ANY WARRANTY; without even the implied warranty of
2255
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2256
+# GNU General Public License for more details.
2257
+#
2258
+# You should have received a copy of the GNU General Public License
2259
+# along with Koha; if not, see <http://www.gnu.org/licenses>.
2260
+
2261
+use Modern::Perl;
2262
+
2263
+use Test::More tests => 2;
2264
+
2265
+use Koha::Database;
2266
+
2267
+my $schema  = Koha::Database->new->schema;
2268
+
2269
+subtest 'Test class imports' => sub {
2270
+    plan tests => 2;
2271
+
2272
+    use_ok('Koha::Patron::Message::Transport::Type');
2273
+    use_ok('Koha::Patron::Message::Transport::Types');
2274
+};
2275
+
2276
+subtest 'Test Koha::Patron::Message::Transport::Types' => sub {
2277
+    plan tests => 2;
2278
+
2279
+    $schema->storage->txn_begin;
2280
+
2281
+    my $transport_type = Koha::Patron::Message::Transport::Type->new({
2282
+        message_transport_type => 'test'
2283
+    })->store;
2284
+
2285
+    is($transport_type->message_transport_type, 'test',
2286
+       'Added a new message transport type.');
2287
+
2288
+    $transport_type->delete;
2289
+    is(Koha::Patron::Message::Transport::Types->find('test'), undef,
2290
+       'Deleted the message transport type.');
2291
+
2292
+    $schema->storage->txn_rollback;
2293
+};
2294
+
2295
+1;
2296
diff --git a/t/db_dependent/Koha/Patron/Message/Transports.t b/t/db_dependent/Koha/Patron/Message/Transports.t
2297
new file mode 100644
2298
index 0000000..b9296fd
2299
--- /dev/null
2300
+++ b/t/db_dependent/Koha/Patron/Message/Transports.t
2301
@@ -0,0 +1,119 @@
2302
+#!/usr/bin/perl
2303
+
2304
+# Copyright 2017 Koha-Suomi Oy
2305
+#
2306
+# This file is part of Koha
2307
+#
2308
+# Koha is free software; you can redistribute it and/or modify it
2309
+# under the terms of the GNU General Public License as published by
2310
+# the Free Software Foundation; either version 3 of the License, or
2311
+# (at your option) any later version.
2312
+#
2313
+# Koha is distributed in the hope that it will be useful, but
2314
+# WITHOUT ANY WARRANTY; without even the implied warranty of
2315
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2316
+# GNU General Public License for more details.
2317
+#
2318
+# You should have received a copy of the GNU General Public License
2319
+# along with Koha; if not, see <http://www.gnu.org/licenses>.
2320
+
2321
+use Modern::Perl;
2322
+
2323
+use Test::More tests => 2;
2324
+
2325
+use t::lib::TestBuilder;
2326
+
2327
+use Koha::Notice::Templates;
2328
+use Koha::Patron::Message::Attributes;
2329
+use Koha::Patron::Message::Transport::Types;
2330
+
2331
+my $schema  = Koha::Database->new->schema;
2332
+my $builder = t::lib::TestBuilder->new;
2333
+
2334
+subtest 'Test class imports' => sub {
2335
+    plan tests => 2;
2336
+
2337
+    use_ok('Koha::Patron::Message::Transport');
2338
+    use_ok('Koha::Patron::Message::Transports');
2339
+};
2340
+
2341
+subtest 'Test Koha::Patron::Message::Transports' => sub {
2342
+    plan tests => 2;
2343
+
2344
+    $schema->storage->txn_begin;
2345
+
2346
+    my $attribute = build_a_test_attribute();
2347
+    my $mtt       = build_a_test_transport_type();
2348
+    my $letter    = build_a_test_letter({
2349
+        mtt => $mtt->message_transport_type
2350
+    });
2351
+
2352
+    my $transport = Koha::Patron::Message::Transport->new({
2353
+        message_attribute_id   => $attribute->message_attribute_id,
2354
+        message_transport_type => $mtt->message_transport_type,
2355
+        is_digest              => 0,
2356
+        letter_module          => $letter->module,
2357
+        letter_code            => $letter->code,
2358
+    })->store;
2359
+
2360
+    is($transport->message_attribute_id, $attribute->message_attribute_id,
2361
+       'Added a new messaging transport.');
2362
+
2363
+    $transport->delete;
2364
+    is(Koha::Patron::Message::Transports->search({
2365
+        message_attribute_id => $attribute->message_attribute_id,
2366
+        message_transport_type => $mtt->message_transport_type,
2367
+        is_digest => 0
2368
+    })->count, 0, 'Deleted the messaging transport.');
2369
+
2370
+    $schema->storage->txn_rollback;
2371
+};
2372
+
2373
+sub build_a_test_attribute {
2374
+    my ($params) = @_;
2375
+
2376
+    $params->{takes_days} = $params->{takes_days} && $params->{takes_days} > 0
2377
+                            ? 1 : 0;
2378
+
2379
+    my $attribute = $builder->build({
2380
+        source => 'MessageAttribute',
2381
+        value => $params,
2382
+    });
2383
+
2384
+    return Koha::Patron::Message::Attributes->find(
2385
+        $attribute->{message_attribute_id}
2386
+    );
2387
+}
2388
+
2389
+sub build_a_test_letter {
2390
+    my ($params) = @_;
2391
+
2392
+    my $mtt = $params->{mtt} ? $params->{mtt} : 'email';
2393
+    my $branchcode     = $builder->build({
2394
+        source => 'Branch' })->{branchcode};
2395
+    my $letter = $builder->build({
2396
+        source => 'Letter',
2397
+        value => {
2398
+            branchcode => '',
2399
+            is_html => 0,
2400
+            message_transport_type => $mtt
2401
+        }
2402
+    });
2403
+
2404
+    return Koha::Notice::Templates->find({
2405
+        module => $letter->{module},
2406
+        code   => $letter->{code},
2407
+        branchcode => $letter->{branchcode},
2408
+    });
2409
+}
2410
+
2411
+sub build_a_test_transport_type {
2412
+    my $mtt = $builder->build({
2413
+        source => 'MessageTransportType' });
2414
+
2415
+    return Koha::Patron::Message::Transport::Types->find(
2416
+        $mtt->{message_transport_type}
2417
+    );
2418
+}
2419
+
2420
+1;
2421
-- 
2422
2.7.4
(-)a/Koha/Exceptions.pm (-1 / +7 lines)
Lines 24-30 use Exception::Class ( Link Here
24
    },
24
    },
25
    'Koha::Exceptions::MissingParameter' => {
25
    'Koha::Exceptions::MissingParameter' => {
26
        isa => 'Koha::Exceptions::Exception',
26
        isa => 'Koha::Exceptions::Exception',
27
        description => 'A required parameter is missing'
27
        description => 'A required parameter is missing',
28
        fields => ['parameter'],
29
    },
30
    'Koha::Exceptions::TooManyParameters' => {
31
        isa => 'Koha::Exceptions::Exception',
32
        description => 'Too many parameters given',
33
        fields => ['parameter'],
28
    },
34
    },
29
    'Koha::Exceptions::NoChanges' => {
35
    'Koha::Exceptions::NoChanges' => {
30
        isa => 'Koha::Exceptions::Exception',
36
        isa => 'Koha::Exceptions::Exception',
(-)a/Koha/Patron.pm (+42 lines)
Lines 39-44 use Koha::Patron::Categories; Link Here
39
use Koha::Patron::HouseboundProfile;
39
use Koha::Patron::HouseboundProfile;
40
use Koha::Patron::HouseboundRole;
40
use Koha::Patron::HouseboundRole;
41
use Koha::Patron::Images;
41
use Koha::Patron::Images;
42
use Koha::Patron::Message::Preferences;
42
use Koha::Patrons;
43
use Koha::Patrons;
43
use Koha::Virtualshelves;
44
use Koha::Virtualshelves;
44
use Koha::Club::Enrollments;
45
use Koha::Club::Enrollments;
Lines 1417-1422 sub _anonymize_column { Link Here
1417
    $self->$col($val);
1418
    $self->$col($val);
1418
}
1419
}
1419
1420
1421
=head3 set_default_messaging_preferences
1422
1423
    $patron->set_default_messaging_preferences
1424
1425
Sets default messaging preferences on patron.
1426
1427
See Koha::Patron::Message::Preference(s) for more documentation, especially on
1428
thrown exceptions.
1429
1430
=cut
1431
1432
sub set_default_messaging_preferences {
1433
    my ($self, $categorycode) = @_;
1434
1435
    my $options = Koha::Patron::Message::Preferences->get_options;
1436
1437
    foreach my $option (@$options) {
1438
        # Check that this option has preference configuration for this category
1439
        unless (Koha::Patron::Message::Preferences->search({
1440
            message_attribute_id => $option->{message_attribute_id},
1441
            categorycode         => $categorycode || $self->categorycode,
1442
        })->count) {
1443
            next;
1444
        }
1445
1446
        # Delete current setting
1447
        Koha::Patron::Message::Preferences->search({
1448
            borrowernumber => $self->borrowernumber,
1449
             message_attribute_id => $option->{message_attribute_id},
1450
        })->delete;
1451
1452
        Koha::Patron::Message::Preference->new_from_default({
1453
            borrowernumber => $self->borrowernumber,
1454
            categorycode   => $categorycode || $self->categorycode,
1455
            message_attribute_id => $option->{message_attribute_id},
1456
        });
1457
    }
1458
1459
    return $self;
1460
}
1461
1420
=head2 Internal methods
1462
=head2 Internal methods
1421
1463
1422
=head3 _type
1464
=head3 _type
(-)a/Koha/Patron/Message/Attribute.pm (+50 lines)
Line 0 Link Here
1
package Koha::Patron::Message::Attribute;
2
3
# Copyright Koha-Suomi Oy 2016
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 3 of the License, or (at your option) any later
10
# version.a
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use Modern::Perl;
21
22
use Koha::Database;
23
24
use base qw(Koha::Object);
25
26
=head1 NAME
27
28
Koha::Patron::Message::Attribute - Koha Patron Message Attribute object class
29
30
=head1 API
31
32
=head2 Class Methods
33
34
=cut
35
36
=head3 type
37
38
=cut
39
40
sub _type {
41
    return 'MessageAttribute';
42
}
43
44
=head1 AUTHOR
45
46
Lari Taskula <lari.taskula@jns.fi>
47
48
=cut
49
50
1;
(-)a/Koha/Patron/Message/Attributes.pm (+55 lines)
Line 0 Link Here
1
package Koha::Patron::Message::Attributes;
2
3
# Copyright Koha-Suomi Oy 2016
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 3 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use Modern::Perl;
21
22
use Koha::Database;
23
use Koha::Patron::Message::Attribute;
24
25
use base qw(Koha::Objects);
26
27
=head1 NAME
28
29
Koha::Patron::Message::Attributes - Koha Patron Message Attributes object class
30
31
=head1 API
32
33
=head2 Class Methods
34
35
=cut
36
37
=head3 type
38
39
=cut
40
41
sub _type {
42
    return 'MessageAttribute';
43
}
44
45
sub object_class {
46
    return 'Koha::Patron::Message::Attribute';
47
}
48
49
=head1 AUTHOR
50
51
Lari Taskula <lari.taskula@jns.fi>
52
53
=cut
54
55
1;
(-)a/Koha/Patron/Message/Preference.pm (+451 lines)
Line 0 Link Here
1
package Koha::Patron::Message::Preference;
2
3
# Copyright Koha-Suomi Oy 2016
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 3 of the License, or (at your option) any later
10
# version.a
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use Modern::Perl;
21
22
use Koha::Database;
23
use Koha::Exceptions;
24
use Koha::Patron::Categories;
25
use Koha::Patron::Message::Attributes;
26
use Koha::Patron::Message::Preferences;
27
use Koha::Patron::Message::Transport::Preferences;
28
use Koha::Patron::Message::Transport::Types;
29
use Koha::Patron::Message::Transports;
30
use Koha::Patrons;
31
32
use base qw(Koha::Object);
33
34
=head1 NAME
35
36
Koha::Patron::Message::Preference - Koha Patron Message Preference object class
37
38
=head1 API
39
40
=head2 Class Methods
41
42
=cut
43
44
=head3 new
45
46
my $preference = Koha::Patron::Message::Preference->new({
47
   borrowernumber => 123,
48
   #categorycode => 'ABC',
49
   message_attribute_id => 4,
50
   message_transport_types => ['email', 'sms'], # see documentation below
51
   wants_digest => 1,
52
   days_in_advance => 7,
53
});
54
55
Takes either borrowernumber or categorycode, but not both.
56
57
days_in_advance may not be available. See message_attributes table for takes_days
58
configuration.
59
60
wants_digest may not be available. See message_transports table for is_digest
61
configuration.
62
63
You can instantiate a new object without custom validation errors, but when
64
storing, validation may throw exceptions. See C<validate()> for more
65
documentation.
66
67
C<message_transport_types> is a parameter that is not actually a column in this
68
Koha-object. Given this parameter, the message transport types will be added as
69
related transport types for this object. For get and set, you can access them via
70
subroutine C<message_transport_types()> in this class.
71
72
=cut
73
74
sub new {
75
    my ($class, $params) = @_;
76
77
    my $types = $params->{'message_transport_types'};
78
    delete $params->{'message_transport_types'};
79
80
    my $self = $class->SUPER::new($params);
81
82
    $self->_set_message_transport_types($types);
83
84
    return $self;
85
}
86
87
=head3 new_from_default
88
89
my $preference = Koha::Patron::Message::Preference->new_from_default({
90
    borrowernumber => 123,
91
    categorycode   => 'ABC',   # if not given, patron's categorycode will be used
92
    message_attribute_id => 1,
93
});
94
95
NOTE: This subroutine initializes and STORES the object (in order to set
96
message transport types for the preference), so no need to call ->store when
97
preferences are initialized via this method.
98
99
Stores default messaging preference for C<categorycode> to patron for given
100
C<message_attribute_id>.
101
102
Throws Koha::Exceptions::MissingParameter if any of following is missing:
103
- borrowernumber
104
- message_attribute_id
105
106
Throws Koha::Exceptions::ObjectNotFound if default preferences are not found.
107
108
=cut
109
110
sub new_from_default {
111
    my ($class, $params) = @_;
112
113
    my @required = qw(borrowernumber message_attribute_id);
114
    foreach my $p (@required) {
115
        Koha::Exceptions::MissingParameter->throw(
116
            error => 'Missing required parameter.',
117
            parameter => $p,
118
        ) unless exists $params->{$p};
119
    }
120
    unless ($params->{'categorycode'}) {
121
        my $patron = Koha::Patrons->find($params->{borrowernumber});
122
        $params->{'categorycode'} = $patron->categorycode;
123
    }
124
125
    my $default = Koha::Patron::Message::Preferences->find({
126
        categorycode => $params->{'categorycode'},
127
        message_attribute_id => $params->{'message_attribute_id'},
128
    });
129
    Koha::Exceptions::ObjectNotFound->throw(
130
        error => 'Default messaging preference for given categorycode and'
131
        .' message_attribute_id cannot be found.',
132
    ) unless $default;
133
    $default = $default->unblessed;
134
135
    # Add a new messaging preference for patron
136
    my $self = $class->SUPER::new({
137
        borrowernumber => $params->{'borrowernumber'},
138
        message_attribute_id => $default->{'message_attribute_id'},
139
        days_in_advance => $default->{'days_in_advance'},
140
        wants_digest => $default->{'wants_digest'},
141
    })->store;
142
143
    # Set default messaging transport types
144
    my $default_transport_types =
145
    Koha::Patron::Message::Transport::Preferences->search({
146
        borrower_message_preference_id =>
147
                    $default->{'borrower_message_preference_id'}
148
    });
149
    while (my $transport = $default_transport_types->next) {
150
        Koha::Patron::Message::Transport::Preference->new({
151
            borrower_message_preference_id => $self->borrower_message_preference_id,
152
            message_transport_type => $transport->message_transport_type,
153
        })->store;
154
    }
155
156
    return $self;
157
}
158
159
=head3 message_name
160
161
$preference->message_name
162
163
Gets message_name for this messaging preference.
164
165
Setter not implemented.
166
167
=cut
168
169
sub message_name {
170
    my ($self) = @_;
171
172
    if ($self->{'_message_name'}) {
173
        return $self->{'_message_name'};
174
    }
175
    $self->{'_message_name'} = Koha::Patron::Message::Attributes->find({
176
        message_attribute_id => $self->message_attribute_id,
177
    })->message_name;
178
    return $self->{'_message_name'};
179
}
180
181
=head3 message_transport_types
182
183
$preference->message_transport_types
184
Returns a HASHREF of message transport types for this messaging preference, e.g.
185
if ($preference->message_transport_types->{'email'}) {
186
    # email is one of the transport preferences
187
}
188
189
$preference->message_transport_types('email', 'sms');
190
Sets the given message transport types for this messaging preference
191
192
=cut
193
194
sub message_transport_types {
195
    my $self = shift;
196
197
    unless (@_) {
198
        if ($self->{'_message_transport_types'}) {
199
            return $self->{'_message_transport_types'};
200
        }
201
        map {
202
            my $transport = Koha::Patron::Message::Transports->find({
203
                message_attribute_id => $self->message_attribute_id,
204
                message_transport_type => $_->message_transport_type,
205
                is_digest => $self->wants_digest
206
            });
207
            unless ($transport) {
208
                my $logger = Koha::Logger->get;
209
                $logger->warn(
210
                    $self->message_name . ' has no transport with '.
211
                    $_->message_transport_type . ' (digest: '.
212
                    ($self->wants_digest ? 'yes':'no').').'
213
                );
214
            }
215
            $self->{'_message_transport_types'}->{$_->message_transport_type}
216
                = $transport ? $transport->letter_code : ' ';
217
        }
218
        Koha::Patron::Message::Transport::Preferences->search({
219
            borrower_message_preference_id => $self->borrower_message_preference_id,
220
        })->as_list;
221
        return $self->{'_message_transport_types'} || {};
222
    }
223
    else {
224
        $self->_set_message_transport_types(@_);
225
        return $self;
226
    }
227
}
228
229
=head3 set
230
231
$preference->set({
232
    message_transport_types => ['sms', 'phone'],
233
    wants_digest => 0,
234
})->store;
235
236
Sets preference object values and additionally message_transport_types if given.
237
238
=cut
239
240
sub set {
241
    my ($self, $params) = @_;
242
243
    my $mtt = $params->{'message_transport_types'};
244
    delete $params->{'message_transport_types'};
245
246
    $self->SUPER::set($params) if $params;
247
    if ($mtt) {
248
        $self->message_transport_types($mtt);
249
    }
250
251
    return $self;
252
}
253
254
=head3 store
255
256
Makes a validation before actual Koha::Object->store so that proper exceptions
257
can be thrown. See C<validate()> for documentation about exceptions.
258
259
=cut
260
261
sub store {
262
    my $self = shift;
263
264
    $self->validate->SUPER::store(@_);
265
266
    # store message transport types
267
    if (exists $self->{'_message_transport_types'}) {
268
        Koha::Patron::Message::Transport::Preferences->search({
269
            borrower_message_preference_id =>
270
                $self->borrower_message_preference_id,
271
        })->delete;
272
        foreach my $type (keys %{$self->{'_message_transport_types'}}) {
273
            Koha::Patron::Message::Transport::Preference->new({
274
                borrower_message_preference_id =>
275
                    $self->borrower_message_preference_id,
276
                message_transport_type => $type,
277
            })->store;
278
        }
279
    }
280
281
    return $self;
282
}
283
284
=head3 validate
285
286
Makes a basic validation for object.
287
288
Throws following exceptions regarding parameters.
289
- Koha::Exceptions::MissingParameter
290
- Koha::Exceptions::TooManyParameters
291
- Koha::Exceptions::BadParameter
292
293
See $_->parameter to identify the parameter causing the exception.
294
295
Throws Koha::Exceptions::DuplicateObject if this preference already exists.
296
297
Returns Koha::Patron::Message::Preference object.
298
299
=cut
300
301
sub validate {
302
    my ($self) = @_;
303
304
    if ($self->borrowernumber && $self->categorycode) {
305
        Koha::Exceptions::TooManyParameters->throw(
306
            error => 'Both borrowernumber and category given, only one accepted',
307
            parameter => ['borrowernumber', 'categorycode'],
308
        );
309
    }
310
    if (!$self->borrowernumber && !$self->categorycode) {
311
        Koha::Exceptions::MissingParameter->throw(
312
            error => 'borrowernumber or category required, none given',
313
            parameter => ['borrowernumber', 'categorycode'],
314
        );
315
    }
316
    if ($self->borrowernumber) {
317
        Koha::Exceptions::BadParameter->throw(
318
            error => 'Patron not found.',
319
            parameter => 'borrowernumber',
320
        ) unless Koha::Patrons->find($self->borrowernumber);
321
    }
322
    if ($self->categorycode) {
323
        Koha::Exceptions::BadParameter->throw(
324
            error => 'Category not found.',
325
            parameter => 'categorycode',
326
        ) unless Koha::Patron::Categories->find($self->categorycode);
327
    }
328
329
    if (!$self->in_storage) {
330
        my $previous = Koha::Patron::Message::Preferences->search({
331
            borrowernumber => $self->borrowernumber,
332
            categorycode   => $self->categorycode,
333
            message_attribute_id => $self->message_attribute_id,
334
        });
335
        if ($previous->count) {
336
            Koha::Exceptions::DuplicateObject->throw(
337
                error => 'A preference for this borrower/category and'
338
                .' message_attribute_id already exists',
339
            );
340
        }
341
    }
342
343
    my $attr = Koha::Patron::Message::Attributes->find(
344
        $self->message_attribute_id
345
    );
346
    unless ($attr) {
347
        Koha::Exceptions::BadParameter->throw(
348
            error => 'Message attribute with id '.$self->message_attribute_id
349
            .' not found',
350
            parameter => 'message_attribute_id'
351
        );
352
    }
353
    if (defined $self->days_in_advance) {
354
        if ($attr && $attr->takes_days == 0) {
355
            Koha::Exceptions::BadParameter->throw(
356
                error => 'days_in_advance cannot be defined for '.
357
                $attr->message_name . '.',
358
                parameter => 'days_in_advance',
359
            );
360
        }
361
        elsif ($self->days_in_advance < 0 || $self->days_in_advance > 30) {
362
            Koha::Exceptions::BadParameter->throw(
363
                error => 'days_in_advance has to be a value between 0-30 for '.
364
                $attr->message_name . '.',
365
                parameter => 'days_in_advance',
366
            );
367
        }
368
    }
369
    if (defined $self->wants_digest) {
370
        my $transports = Koha::Patron::Message::Transports->search({
371
            message_attribute_id => $self->message_attribute_id,
372
            is_digest            => $self->wants_digest ? 1 : 0,
373
        });
374
        Koha::Exceptions::BadParameter->throw(
375
            error => (!$self->wants_digest ? 'Digest must be selected'
376
                                           : 'Digest cannot be selected')
377
            . ' for '.$attr->message_name.'.',
378
            parameter => 'wants_digest',
379
        ) if $transports->count == 0;
380
    }
381
382
    return $self;
383
}
384
385
sub _set_message_transport_types {
386
    my $self = shift;
387
388
    return unless $_[0];
389
390
    $self->{'_message_transport_types'} = undef;
391
    my $types = ref $_[0] eq "ARRAY" ? $_[0] : [@_];
392
    return unless $types;
393
    $self->_validate_message_transport_types({ message_transport_types => $types });
394
    foreach my $type (@$types) {
395
        unless (exists $self->{'_message_transport_types'}->{$type}) {
396
            my $transport = Koha::Patron::Message::Transports->find({
397
                message_attribute_id => $self->message_attribute_id,
398
                message_transport_type => $type
399
            });
400
            unless ($transport) {
401
                Koha::Exceptions::BadParameter->throw(
402
                    error => 'No transport configured for '.$self->message_name.
403
                        " transport type $type.",
404
                    parameter => 'message_transport_types'
405
                );
406
            }
407
            $self->{'_message_transport_types'}->{$type}
408
                = $transport->letter_code;
409
        }
410
    }
411
    return $self;
412
}
413
414
sub _validate_message_transport_types {
415
    my ($self, $params) = @_;
416
417
    if (ref($params) eq 'HASH' && $params->{'message_transport_types'}) {
418
        if (ref($params->{'message_transport_types'}) ne 'ARRAY') {
419
            $params->{'message_transport_types'} = [$params->{'message_transport_types'}];
420
        }
421
        my $types = $params->{'message_transport_types'};
422
423
        foreach my $type (@{$types}) {
424
            unless (Koha::Patron::Message::Transport::Types->find({
425
                message_transport_type => $type
426
            })) {
427
                Koha::Exceptions::BadParameter->throw(
428
                    error => "Message transport type '$type' does not exist",
429
                    parameter => 'message_transport_types',
430
                );
431
            }
432
        }
433
        return $types;
434
    }
435
}
436
437
=head3 type
438
439
=cut
440
441
sub _type {
442
    return 'BorrowerMessagePreference';
443
}
444
445
=head1 AUTHOR
446
447
Lari Taskula <lari.taskula@jns.fi>
448
449
=cut
450
451
1;
(-)a/Koha/Patron/Message/Preferences.pm (+146 lines)
Line 0 Link Here
1
package Koha::Patron::Message::Preferences;
2
3
# Copyright Koha-Suomi Oy 2016
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 3 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use Modern::Perl;
21
22
use Koha::Database;
23
use Koha::Patron::Message::Attributes;
24
use Koha::Patron::Message::Preference;
25
use Koha::Patron::Message::Transports;
26
27
use base qw(Koha::Objects);
28
29
=head1 NAME
30
31
Koha::Patron::Message::Preferences - Koha Patron Message Preferences object class
32
33
=head1 API
34
35
=head2 Class Methods
36
37
=cut
38
39
=head3 find_with_message_name
40
41
Koha::Patron::Message::Preferences->find_with_message_name({
42
    borrowernumber => 123,
43
    message_name => 'Hold_Filled',
44
});
45
46
Converts C<message_name> into C<message_attribute_id> and continues find.
47
48
=cut
49
50
sub find_with_message_name {
51
    my ($self, $id) = @_;
52
53
    if (ref($id) eq "HASH" && $id->{'message_name'}) {
54
        my $attr = Koha::Patron::Message::Attributes->find({
55
            message_name => $id->{'message_name'},
56
        });
57
        $id->{'message_attribute_id'} = ($attr) ?
58
                    $attr->message_attribute_id : undef;
59
        delete $id->{'message_name'};
60
    }
61
62
    return $self->SUPER::find($id);
63
}
64
65
=head3 get_options
66
67
my $messaging_options = Koha::Patron::Message::Preferences->get_options
68
69
Returns an ARRAYref of HASHrefs on available messaging options.
70
71
=cut
72
73
sub get_options {
74
    my ($self) = @_;
75
76
    my $transports = Koha::Patron::Message::Transports->search(undef,
77
        {
78
            join => ['message_attribute'],
79
            '+select' => ['message_attribute.message_name', 'message_attribute.takes_days'],
80
            '+as' => ['message_name', 'takes_days'],
81
        });
82
83
    my $choices;
84
    while (my $transport = $transports->next) {
85
        my $name = $transport->get_column('message_name');
86
        $choices->{$name}->{'message_attribute_id'} = $transport->message_attribute_id;
87
        $choices->{$name}->{'message_name'}         = $name;
88
        $choices->{$name}->{'takes_days'}           = $transport->get_column('takes_days');
89
        $choices->{$name}->{'has_digest'}           ||= 1 if $transport->is_digest;
90
        $choices->{$name}->{'has_digest_off'}       ||= 1 if !$transport->is_digest;
91
        $choices->{$name}->{'transport_'.$transport->get_column('message_transport_type')} = ' ';
92
    }
93
94
    my @return = values %$choices;
95
    @return = sort { $a->{message_attribute_id} <=> $b->{message_attribute_id} } @return;
96
97
    return \@return;
98
}
99
100
=head3 search_with_message_name
101
102
Koha::Patron::Message::Preferences->search_with_message_name({
103
    borrowernumber => 123,
104
    message_name => 'Hold_Filled',
105
});
106
107
Converts C<message_name> into C<message_attribute_id> and continues search. Use
108
Koha::Patron::Message::Preferences->search with a proper join for more complicated
109
searches.
110
111
=cut
112
113
sub search_with_message_name {
114
    my ($self, $params, $attributes) = @_;
115
116
    if (ref($params) eq "HASH" && $params->{'message_name'}) {
117
        my $attr = Koha::Patron::Message::Attributes->find({
118
            message_name => $params->{'message_name'},
119
        });
120
        $params->{'message_attribute_id'} = ($attr) ?
121
                    $attr->message_attribute_id : undef;
122
        delete $params->{'message_name'};
123
    }
124
125
    return $self->SUPER::search($params, $attributes);
126
}
127
128
=head3 type
129
130
=cut
131
132
sub _type {
133
    return 'BorrowerMessagePreference';
134
}
135
136
sub object_class {
137
    return 'Koha::Patron::Message::Preference';
138
}
139
140
=head1 AUTHOR
141
142
Lari Taskula <lari.taskula@jns.fi>
143
144
=cut
145
146
1;
(-)a/Koha/Patron/Message/Transport.pm (+50 lines)
Line 0 Link Here
1
package Koha::Patron::Message::Transport;
2
3
# Copyright Koha-Suomi Oy 2016
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 3 of the License, or (at your option) any later
10
# version.a
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use Modern::Perl;
21
22
use Koha::Database;
23
24
use base qw(Koha::Object);
25
26
=head1 NAME
27
28
Koha::Patron::Message::Transport - Koha Patron Message Transport object class
29
30
=head1 API
31
32
=head2 Class Methods
33
34
=cut
35
36
=head3 type
37
38
=cut
39
40
sub _type {
41
    return 'MessageTransport';
42
}
43
44
=head1 AUTHOR
45
46
Lari Taskula <lari.taskula@jns.fi>
47
48
=cut
49
50
1;
(-)a/Koha/Patron/Message/Transport/Preference.pm (+51 lines)
Line 0 Link Here
1
package Koha::Patron::Message::Transport::Preference;
2
3
# Copyright Koha-Suomi Oy 2016
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 3 of the License, or (at your option) any later
10
# version.a
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use Modern::Perl;
21
22
use Koha::Database;
23
24
use base qw(Koha::Object);
25
26
=head1 NAME
27
28
Koha::Patron::Message::Transport::Preference - Koha Patron Message Transport
29
Preference object class
30
31
=head1 API
32
33
=head2 Class Methods
34
35
=cut
36
37
=head3 type
38
39
=cut
40
41
sub _type {
42
    return 'BorrowerMessageTransportPreference';
43
}
44
45
=head1 AUTHOR
46
47
Lari Taskula <lari.taskula@jns.fi>
48
49
=cut
50
51
1;
(-)a/Koha/Patron/Message/Transport/Preferences.pm (+56 lines)
Line 0 Link Here
1
package Koha::Patron::Message::Transport::Preferences;
2
3
# Copyright Koha-Suomi Oy 2016
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 3 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use Modern::Perl;
21
22
use Koha::Database;
23
use Koha::Patron::Message::Transport::Preference;
24
25
use base qw(Koha::Objects);
26
27
=head1 NAME
28
29
Koha::Patron::Message::Transport::Preferences - Koha Patron Message Transport
30
Preferences object class
31
32
=head1 API
33
34
=head2 Class Methods
35
36
=cut
37
38
=head3 type
39
40
=cut
41
42
sub _type {
43
    return 'BorrowerMessageTransportPreference';
44
}
45
46
sub object_class {
47
    return 'Koha::Patron::Message::Transport::Preference';
48
}
49
50
=head1 AUTHOR
51
52
Lari Taskula <lari.taskula@jns.fi>
53
54
=cut
55
56
1;
(-)a/Koha/Patron/Message/Transport/Type.pm (+51 lines)
Line 0 Link Here
1
package Koha::Patron::Message::Transport::Type;
2
3
# Copyright Koha-Suomi Oy 2016
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 3 of the License, or (at your option) any later
10
# version.a
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use Modern::Perl;
21
22
use Koha::Database;
23
24
use base qw(Koha::Object);
25
26
=head1 NAME
27
28
Koha::Patron::Message::Transport::Type - Koha Patron Message Transport Type
29
object class
30
31
=head1 API
32
33
=head2 Class Methods
34
35
=cut
36
37
=head3 type
38
39
=cut
40
41
sub _type {
42
    return 'MessageTransportType';
43
}
44
45
=head1 AUTHOR
46
47
Lari Taskula <lari.taskula@jns.fi>
48
49
=cut
50
51
1;
(-)a/Koha/Patron/Message/Transport/Types.pm (+56 lines)
Line 0 Link Here
1
package Koha::Patron::Message::Transport::Types;
2
3
# Copyright Koha-Suomi Oy 2016
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 3 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use Modern::Perl;
21
22
use Koha::Database;
23
use Koha::Patron::Message::Transport::Type;
24
25
use base qw(Koha::Objects);
26
27
=head1 NAME
28
29
Koha::Patron::Message::Transport::Types - Koha Patron Message Transport Types
30
object class
31
32
=head1 API
33
34
=head2 Class Methods
35
36
=cut
37
38
=head3 type
39
40
=cut
41
42
sub _type {
43
    return 'MessageTransportType';
44
}
45
46
sub object_class {
47
    return 'Koha::Patron::Message::Transport::Type';
48
}
49
50
=head1 AUTHOR
51
52
Lari Taskula <lari.taskula@jns.fi>
53
54
=cut
55
56
1;
(-)a/Koha/Patron/Message/Transports.pm (+55 lines)
Line 0 Link Here
1
package Koha::Patron::Message::Transports;
2
3
# Copyright Koha-Suomi Oy 2016
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 3 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use Modern::Perl;
21
22
use Koha::Database;
23
use Koha::Patron::Message::Transport;
24
25
use base qw(Koha::Objects);
26
27
=head1 NAME
28
29
Koha::Patron::Message::Transports - Koha Patron Message Transports object class
30
31
=head1 API
32
33
=head2 Class Methods
34
35
=cut
36
37
=head3 type
38
39
=cut
40
41
sub _type {
42
    return 'MessageTransport';
43
}
44
45
sub object_class {
46
    return 'Koha::Patron::Message::Transport';
47
}
48
49
=head1 AUTHOR
50
51
Lari Taskula <lari.taskula@jns.fi>
52
53
=cut
54
55
1;
(-)a/installer/data/mysql/atomicupdate/Bug_14620-Contact-information-validation.perl (+7 lines)
Line 0 Link Here
1
$DBversion = 'XXX';  # will be replaced by the RM
2
if( CheckVersion( $DBversion ) ) {
3
    $dbh->do("INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, `type` ) VALUES ('ValidatePhoneNumber','','','Regex for validation of patron phone numbers.','Textarea')");
4
5
    SetVersion( $DBversion );
6
    print "Upgrade to $DBversion done (Bug 14620 - description)\n";
7
}
(-)a/t/db_dependent/Koha/Patron/Message/Attributes.t (+74 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# Copyright 2017 Koha-Suomi Oy
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
20
use Modern::Perl;
21
22
use Test::More tests => 2;
23
24
use Koha::Database;
25
26
my $schema  = Koha::Database->new->schema;
27
28
subtest 'Test class imports' => sub {
29
    plan tests => 2;
30
31
    use_ok('Koha::Patron::Message::Attribute');
32
    use_ok('Koha::Patron::Message::Attributes');
33
};
34
35
subtest 'Test Koha::Patron::Message::Attributes' => sub {
36
    plan tests => 6;
37
38
    $schema->storage->txn_begin;
39
40
    Koha::Patron::Message::Attribute->new({
41
        message_name => 'Test_Attribute'
42
    })->store;
43
    Koha::Patron::Message::Attribute->new({
44
        message_name => 'Test_Attribute2',
45
        takes_days   => 1
46
    })->store;
47
48
    my $attribute  = Koha::Patron::Message::Attributes->find({
49
        message_name => 'Test_Attribute' });
50
    my $attribute2 = Koha::Patron::Message::Attributes->find({
51
        message_name => 'Test_Attribute2' });
52
53
    is($attribute->message_name, 'Test_Attribute',
54
       'Added a new messaging attribute.');
55
    is($attribute->takes_days, 0,
56
       'For that messaging attribute, takes_days is disabled by default.');
57
    is($attribute2->message_name, 'Test_Attribute2',
58
       'Added another messaging attribute.');
59
    is($attribute2->takes_days, 1,
60
       'takes_days is enabled for that message attribute (as expected).');
61
62
    $attribute->delete;
63
    $attribute2->delete;
64
    is(Koha::Patron::Message::Attributes->find({
65
        message_name => 'Test_Attribute' }), undef,
66
       'Deleted the first message attribute.');
67
    is(Koha::Patron::Message::Attributes->find({
68
        message_name => 'Test_Attribute2' }), undef,
69
       'Deleted the second message attribute.');
70
71
    $schema->storage->txn_rollback;
72
};
73
74
1;
(-)a/t/db_dependent/Koha/Patron/Message/Preferences.t (+719 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# Copyright 2017 Koha-Suomi Oy
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
20
use Modern::Perl;
21
22
use Test::More tests => 7;
23
24
use t::lib::Mocks;
25
use t::lib::TestBuilder;
26
27
use C4::Context;
28
29
use Koha::Notice::Templates;
30
use Koha::Patron::Categories;
31
use Koha::Patron::Message::Attributes;
32
use Koha::Patron::Message::Transport::Types;
33
use Koha::Patron::Message::Transports;
34
use Koha::Patrons;
35
36
use File::Temp qw/tempfile/;
37
use Log::Log4perl;
38
39
my $schema  = Koha::Database->new->schema;
40
my $builder = t::lib::TestBuilder->new;
41
42
subtest 'Test class imports' => sub {
43
    plan tests => 2;
44
45
    use_ok('Koha::Patron::Message::Preference');
46
    use_ok('Koha::Patron::Message::Preferences');
47
};
48
49
subtest 'Test Koha::Patron::Message::Preferences' => sub {
50
    plan tests => 2;
51
52
    $schema->storage->txn_begin;
53
54
    my $attribute = build_a_test_attribute();
55
    my $letter = build_a_test_letter();
56
    my $mtt = build_a_test_transport_type();
57
    Koha::Patron::Message::Transport->new({
58
        message_attribute_id   => $attribute->message_attribute_id,
59
        message_transport_type => $mtt->message_transport_type,
60
        is_digest              => 0,
61
        letter_module          => $letter->module,
62
        letter_code            => $letter->code,
63
    })->store;
64
65
    subtest 'Test for a patron' => sub {
66
        plan tests => 3;
67
68
        my $patron = build_a_test_patron();
69
        Koha::Patron::Message::Preference->new({
70
            borrowernumber       => $patron->borrowernumber,
71
            message_attribute_id => $attribute->message_attribute_id,
72
            wants_digest         => 0,
73
            days_in_advance      => undef,
74
        })->store;
75
76
        my $preference = Koha::Patron::Message::Preferences->find({
77
            borrowernumber       => $patron->borrowernumber,
78
            message_attribute_id => $attribute->message_attribute_id
79
        });
80
        ok($preference->borrower_message_preference_id > 0,
81
           'Added a new messaging preference for patron.');
82
83
        subtest 'Test set not throwing an exception on duplicate object' => sub {
84
            plan tests => 1;
85
86
            Koha::Patron::Message::Attributes->find({
87
                message_attribute_id => $attribute->message_attribute_id
88
            })->set({ takes_days => 1 })->store;
89
            $preference->set({ days_in_advance => 1 })->store;
90
            is(ref($preference), 'Koha::Patron::Message::Preference',
91
             'Updating the preference does not cause duplicate object exception');
92
        };
93
94
        $preference->delete;
95
        is(Koha::Patron::Message::Preferences->search({
96
            borrowernumber       => $patron->borrowernumber,
97
            message_attribute_id => $attribute->message_attribute_id
98
        })->count, 0, 'Deleted the messaging preference.');
99
    };
100
101
    subtest 'Test for a category' => sub {
102
        my $category = build_a_test_category();
103
        Koha::Patron::Message::Preference->new({
104
            categorycode         => $category->categorycode,
105
            message_attribute_id => $attribute->message_attribute_id,
106
            wants_digest         => 0,
107
            days_in_advance      => undef,
108
        })->store;
109
110
        my $preference = Koha::Patron::Message::Preferences->find({
111
            categorycode         => $category->categorycode,
112
            message_attribute_id => $attribute->message_attribute_id
113
        });
114
        ok($preference->borrower_message_preference_id > 0,
115
           'Added a new messaging preference for category.');
116
117
        $preference->delete;
118
        is(Koha::Patron::Message::Preferences->search({
119
            categorycode         => $category->categorycode,
120
            message_attribute_id => $attribute->message_attribute_id
121
        })->count, 0, 'Deleted the messaging preference.');
122
    };
123
124
    $schema->storage->txn_rollback;
125
};
126
127
subtest 'Test Koha::Patron::Message::Preferences->get_options' => sub {
128
    plan tests => 2;
129
130
    subtest 'Test method availability and return value' => sub {
131
        plan tests => 3;
132
133
        ok(Koha::Patron::Message::Preferences->can('get_options'),
134
            'Method get_options is available.');
135
        ok(my $options = Koha::Patron::Message::Preferences->get_options,
136
            'Called get_options successfully.');
137
        is(ref($options), 'ARRAY', 'get_options returns a ARRAYref');
138
    };
139
140
    subtest 'Make sure options are correct' => sub {
141
        $schema->storage->txn_begin;
142
        my $options = Koha::Patron::Message::Preferences->get_options;
143
144
        foreach my $option (@$options) {
145
            my $n = $option->{'message_name'};
146
            my $attr = Koha::Patron::Message::Attributes->find($option->{'message_attribute_id'});
147
            is($option->{'message_attribute_id'}, $attr->message_attribute_id,
148
               '$n: message_attribute_id is set');
149
            is($option->{'message_name'}, $attr->message_name, '$n: message_name is set');
150
            is($option->{'takes_days'}, $attr->takes_days, '$n: takes_days is set');
151
            my $transports = Koha::Patron::Message::Transports->search({
152
                message_attribute_id => $option->{'message_attribute_id'},
153
                is_digest => $option->{'has_digest'} || 0,
154
            });
155
            while (my $trnzport = $transports->next) {
156
                is($option->{'has_digest'} || 0, $trnzport->is_digest, '$n: has_digest is set for '.$trnzport->message_transport_type);
157
                is($option->{'transport_'.$trnzport->message_transport_type}, ' ', '$n: transport_'.$trnzport->message_transport_type.' is set');
158
            }
159
        }
160
161
        $schema->storage->txn_rollback;
162
    };
163
};
164
165
subtest 'Add preferences from defaults' => sub {
166
    plan tests => 3;
167
168
    $schema->storage->txn_begin;
169
170
    my $patron = build_a_test_patron();
171
    my ($default, $mtt1, $mtt2) = build_a_test_category_preference({
172
        patron => $patron,
173
    });
174
    ok(Koha::Patron::Message::Preference->new_from_default({
175
        borrowernumber       => $patron->borrowernumber,
176
        categorycode         => $patron->categorycode,
177
        message_attribute_id => $default->message_attribute_id,
178
    })->store, 'Added a default preference to patron.');
179
    ok(my $pref = Koha::Patron::Message::Preferences->find({
180
        borrowernumber       => $patron->borrowernumber,
181
        message_attribute_id => $default->message_attribute_id,
182
    }), 'Found the default preference from patron.');
183
    is(Koha::Patron::Message::Transport::Preferences->search({
184
        borrower_message_preference_id => $pref->borrower_message_preference_id
185
    })->count, 2, 'Found the two transport types that we set earlier');
186
187
    $schema->storage->txn_rollback;
188
};
189
190
subtest 'Test Koha::Patron::Message::Preference->message_transport_types' => sub {
191
    plan tests => 4;
192
193
    ok(Koha::Patron::Message::Preference->can('message_transport_types'),
194
       'Method message_transport_types available');
195
196
    subtest 'get message_transport_types' => sub {
197
        plan tests => 5;
198
199
        $schema->storage->txn_begin;
200
201
        my $patron = build_a_test_patron();
202
        my ($preference, $mtt1, $mtt2) = build_a_test_complete_preference({
203
            patron => $patron
204
        });
205
        Koha::Patron::Message::Transport::Preferences->search({
206
            borrower_message_preference_id => $preference->borrower_message_preference_id,
207
        })->delete;
208
        Koha::Patron::Message::Transport::Preference->new({
209
            borrower_message_preference_id => $preference->borrower_message_preference_id,
210
            message_transport_type => $mtt1->message_transport_type,
211
        })->store;
212
        Koha::Patron::Message::Transport::Preference->new({
213
            borrower_message_preference_id => $preference->borrower_message_preference_id,
214
            message_transport_type => $mtt2->message_transport_type,
215
        })->store;
216
        my $stored_transports = Koha::Patron::Message::Transport::Preferences->search({
217
            borrower_message_preference_id => $preference->borrower_message_preference_id,
218
        });
219
        my $transport1 = Koha::Patron::Message::Transports->find({
220
            message_attribute_id => $preference->message_attribute_id,
221
            message_transport_type => $mtt1->message_transport_type,
222
        });
223
        my $transport2 = Koha::Patron::Message::Transports->find({
224
            message_attribute_id => $preference->message_attribute_id,
225
            message_transport_type => $mtt2->message_transport_type,
226
        });
227
        my $transports = $preference->message_transport_types;
228
        is(keys %{$transports}, $stored_transports->count,
229
           '->message_transport_types gets correct amount of transport types.');
230
        is($transports->{$stored_transports->next->message_transport_type},
231
           $transport1->letter_code, 'Found correct message transport type and letter code.');
232
        is($transports->{$stored_transports->next->message_transport_type},
233
           $transport2->letter_code, 'Found correct message transport type and letter code.');
234
        ok(!$preference->message_transport_types->{'nonexistent'},
235
           'Didn\'t find nonexistent transport type.');
236
237
        subtest 'test logging of warnings by invalid message transport type' => sub {
238
            plan tests => 2;
239
240
            my $log = mytempfile();
241
            my $conf = mytempfile( <<"HERE"
242
log4perl.logger.opac = WARN, OPAC
243
log4perl.appender.OPAC=Log::Log4perl::Appender::TestBuffer
244
log4perl.appender.OPAC.filename=$log
245
log4perl.appender.OPAC.mode=append
246
log4perl.appender.OPAC.layout=SimpleLayout
247
log4perl.logger.intranet = WARN, INTRANET
248
log4perl.appender.INTRANET=Log::Log4perl::Appender::TestBuffer
249
log4perl.appender.INTRANET.filename=$log
250
log4perl.appender.INTRANET.mode=append
251
log4perl.appender.INTRANET.layout=SimpleLayout
252
HERE
253
            );
254
            t::lib::Mocks::mock_config('log4perl_conf', $conf);
255
            my $appenders = Log::Log4perl->appenders;
256
            my $appender = Log::Log4perl->appenders->{OPAC};
257
258
            my $pref = Koha::Patron::Message::Preferences->find(
259
                $preference->borrower_message_preference_id
260
            );
261
            my $transports = $pref->message_transport_types;
262
            is($appender, undef, 'Nothing in buffer yet');
263
264
            my $mtt_new = build_a_test_transport_type();
265
            Koha::Patron::Message::Transport::Preference->new({
266
                borrower_message_preference_id =>
267
                                $pref->borrower_message_preference_id,
268
                message_transport_type => $mtt_new->message_transport_type,
269
            })->store;
270
            $pref = Koha::Patron::Message::Preferences->find(
271
                $pref->borrower_message_preference_id
272
            );
273
            $transports = $pref->message_transport_types;
274
            $appender = Log::Log4perl->appenders->{OPAC};
275
            my $name = $pref->message_name;
276
            my $tt = $mtt_new->message_transport_type;
277
            like($appender->buffer, qr/WARN - $name has no transport with $tt/,
278
                 'Logged invalid message transport type');
279
        };
280
281
        $schema->storage->txn_rollback;
282
    };
283
284
    subtest 'set message_transport_types' => sub {
285
        plan tests => 6;
286
287
        $schema->storage->txn_begin;
288
289
        my $patron = build_a_test_patron();
290
        my ($preference, $mtt1, $mtt2) = build_a_test_complete_preference({
291
            patron => $patron
292
        });
293
294
        my $mtt1_str = $mtt1->message_transport_type;
295
        my $mtt2_str = $mtt2->message_transport_type;
296
        # 1/3, use message_transport_types(list)
297
        Koha::Patron::Message::Transport::Preferences->search({
298
            borrower_message_preference_id => $preference->borrower_message_preference_id,
299
        })->delete;
300
        ok($preference->message_transport_types($mtt1_str, $mtt2_str)->store,
301
           '1/3 Set returned true.');
302
        my $stored_transports = Koha::Patron::Message::Transport::Preferences->search({
303
            borrower_message_preference_id => $preference->borrower_message_preference_id,
304
            '-or' => [
305
                message_transport_type => $mtt1_str,
306
                message_transport_type => $mtt2_str
307
            ]
308
        });
309
        is($stored_transports->count, 2, 'Two transports selected');
310
311
        # 2/3, use message_transport_types(ARRAYREF)
312
        Koha::Patron::Message::Transport::Preferences->search({
313
            borrower_message_preference_id => $preference->borrower_message_preference_id,
314
        })->delete;
315
        ok($preference->message_transport_types([$mtt1_str, $mtt2_str])->store,
316
           '2/3 Set returned true.');
317
        $stored_transports = Koha::Patron::Message::Transport::Preferences->search({
318
            borrower_message_preference_id => $preference->borrower_message_preference_id,
319
            '-or' => [
320
                message_transport_type => $mtt1_str,
321
                message_transport_type => $mtt2_str
322
            ]
323
        });
324
        is($stored_transports->count, 2, 'Two transports selected');
325
326
        # 3/3, use set({ message_transport_types => ARRAYREF })
327
        Koha::Patron::Message::Transport::Preferences->search({
328
            borrower_message_preference_id => $preference->borrower_message_preference_id,
329
        })->delete;
330
        ok($preference->set({
331
            message_transport_types => [$mtt1_str, $mtt2_str]})->store,
332
           '3/3 Set returned true.');
333
        $stored_transports = Koha::Patron::Message::Transport::Preferences->search({
334
            borrower_message_preference_id => $preference->borrower_message_preference_id,
335
            '-or' => [
336
                message_transport_type => $mtt1_str,
337
                message_transport_type => $mtt2_str
338
            ]
339
        });
340
        is($stored_transports->count, 2, 'Two transports selected');
341
342
        $schema->storage->txn_rollback;
343
    };
344
345
    subtest 'new message_transport_types' => sub {
346
        plan tests => 3;
347
348
        $schema->storage->txn_begin;
349
350
        my $patron    = build_a_test_patron();
351
        my $letter    = build_a_test_letter();
352
        my $attribute = build_a_test_attribute();
353
        my $mtt       = build_a_test_transport_type();
354
        Koha::Patron::Message::Transport->new({
355
            message_attribute_id   => $attribute->message_attribute_id,
356
            message_transport_type => $mtt->message_transport_type,
357
            is_digest              => 0,
358
            letter_module          => $letter->module,
359
            letter_code            => $letter->code,
360
        })->store;
361
        ok(my $preference = Koha::Patron::Message::Preference->new({
362
            borrowernumber => $patron->borrowernumber,
363
            message_attribute_id => $attribute->message_attribute_id,
364
            wants_digest => 0,
365
            days_in_advance => undef,
366
            message_transport_types => $mtt->message_transport_type,
367
        })->store, 'Added a new messaging preference and transport types to patron.');
368
        ok($preference->message_transport_types->{$mtt->message_transport_type},
369
           'The transport type is stored in the object.');
370
        my $stored_transports = Koha::Patron::Message::Transport::Preferences->search({
371
            borrower_message_preference_id => $preference->borrower_message_preference_id,
372
        });
373
        is($stored_transports->next->message_transport_type, $mtt->message_transport_type,
374
           'The transport type is stored in the database.');
375
376
        $schema->storage->txn_rollback;
377
    };
378
};
379
380
subtest 'Test Koha::Patron::Message::Preference->message_name' => sub {
381
    plan tests => 1;
382
383
    $schema->storage->txn_begin;
384
385
    my $patron      = build_a_test_patron();
386
    my $attribute   = build_a_test_attribute();
387
    my ($preference, $mtt1, $mtt2) = build_a_test_complete_preference({
388
        patron => $patron,
389
        attr   => $attribute,
390
    });
391
    my $message_name_pref = Koha::Patron::Message::Preferences->search_with_message_name({
392
        borrowernumber => $patron->{'borrowernumber'},
393
        message_name => $attribute->message_name,
394
    })->next;
395
    is($message_name_pref->message_name, $attribute->message_name, "Found preference with message_name");
396
397
    $schema->storage->txn_rollback;
398
};
399
400
subtest 'Test adding a new preference with invalid parameters' => sub {
401
    plan tests => 4;
402
403
    subtest 'Missing parameters' => sub {
404
        plan tests => 1;
405
406
        eval { Koha::Patron::Message::Preference->new->store };
407
        is(ref $@, 'Koha::Exceptions::MissingParameter',
408
            'Adding a message preference without parameters'
409
            .' => Koha::Exceptions::MissingParameter');
410
    };
411
412
    subtest 'Too many parameters' => sub {
413
        plan tests => 1;
414
415
        $schema->storage->txn_begin;
416
417
        my $patron = build_a_test_patron();
418
        eval { Koha::Patron::Message::Preference->new({
419
            borrowernumber => $patron->borrowernumber,
420
            categorycode   => $patron->categorycode,
421
        })->store };
422
        is(ref $@, 'Koha::Exceptions::TooManyParameters',
423
            'Adding a message preference for both borrowernumber and categorycode'
424
            .' => Koha::Exceptions::TooManyParameters');
425
426
        $schema->storage->txn_rollback;
427
    };
428
429
    subtest 'Bad parameter' => sub {
430
        plan tests => 22;
431
432
        $schema->storage->txn_begin;
433
434
        eval { Koha::Patron::Message::Preference->new({
435
                borrowernumber => -999,
436
            })->store };
437
        is(ref $@, 'Koha::Exceptions::BadParameter',
438
            'Adding a message preference with invalid borrowernumber'
439
            .' => Koha::Exceptions::BadParameter');
440
        is ($@->parameter, 'borrowernumber', 'The previous exception tells us it'
441
            .' was the borrowernumber.');
442
443
        eval { Koha::Patron::Message::Preference->new({
444
                categorycode => 'nonexistent',
445
            })->store };
446
        is(ref $@, 'Koha::Exceptions::BadParameter',
447
            'Adding a message preference with invalid categorycode'
448
            .' => Koha::Exceptions::BadParameter');
449
        is($@->parameter, 'categorycode', 'The previous exception tells us it'
450
            .' was the categorycode.');
451
452
        my $attribute = build_a_test_attribute({ takes_days => 0 });
453
        my $patron    = build_a_test_patron();
454
        eval { Koha::Patron::Message::Preference->new({
455
                borrowernumber => $patron->borrowernumber,
456
                message_attribute_id => $attribute->message_attribute_id,
457
                days_in_advance => 10,
458
            })->store };
459
        is(ref $@, 'Koha::Exceptions::BadParameter',
460
            'Adding a message preference with days in advance option when not'
461
            .' available => Koha::Exceptions::BadParameter');
462
        is($@->parameter, 'days_in_advance', 'The previous exception tells us it'
463
            .' was the days_in_advance.');
464
465
        $attribute->set({ takes_days => 1 })->store;
466
        eval { Koha::Patron::Message::Preference->new({
467
                borrowernumber => $patron->borrowernumber,
468
                message_attribute_id => $attribute->message_attribute_id,
469
                days_in_advance => 31,
470
            })->store };
471
        is(ref $@, 'Koha::Exceptions::BadParameter',
472
            'Adding a message preference with days in advance option too large'
473
            .' => Koha::Exceptions::BadParameter');
474
        is($@->parameter, 'days_in_advance', 'The previous exception tells us it'
475
            .' was the days_in_advance.');
476
477
        eval { Koha::Patron::Message::Preference->new({
478
                borrowernumber => $patron->borrowernumber,
479
                message_transport_types => ['nonexistent']
480
            })->store };
481
        is (ref $@, 'Koha::Exceptions::BadParameter',
482
            'Adding a message preference with invalid message_transport_type'
483
            .' => Koha::Exceptions::BadParameter');
484
        is ($@->parameter, 'message_transport_types', 'The previous exception '
485
            .'tells us it was the message_transport_types.');
486
487
        my $mtt_new = build_a_test_transport_type();
488
        eval {
489
            Koha::Patron::Message::Preference->new({
490
                borrowernumber => $patron->borrowernumber,
491
                message_attribute_id => $attribute->message_attribute_id,
492
                message_transport_types => [$mtt_new->message_transport_type],
493
                wants_digest => 1,
494
            })->store };
495
        is (ref $@, 'Koha::Exceptions::BadParameter',
496
            'Adding a message preference with invalid message_transport_type'
497
           .' => Koha::Exceptions::BadParameter');
498
        is ($@->parameter, 'message_transport_types', 'The previous exception '
499
            .'tells us it was the message_transport_types.');
500
        like ($@->error, qr/^No transport configured/, 'Exception is because of '
501
            .'given message_transport_type is not a valid option.');
502
503
        eval {
504
            Koha::Patron::Message::Preference->new({
505
                borrowernumber => $patron->borrowernumber,
506
                message_attribute_id => $attribute->message_attribute_id,
507
                message_transport_types => [],
508
                wants_digest => 1,
509
            })->store };
510
        is (ref $@, 'Koha::Exceptions::BadParameter',
511
            'Adding a message preference with invalid message_transport_type'
512
            .' => Koha::Exceptions::BadParameter');
513
        is ($@->parameter, 'wants_digest', 'The previous exception tells us it'
514
            .' was the wants_digest');
515
        like ($@->error, qr/^Digest cannot be selected/, 'Exception s because of'
516
            .' given digest is not available for this transport.');
517
518
        eval {
519
            Koha::Patron::Message::Preference->new({
520
                borrowernumber => $patron->borrowernumber,
521
                message_attribute_id => $attribute->message_attribute_id,
522
                message_transport_types => [],
523
                wants_digest => 0,
524
            })->store };
525
        is (ref $@, 'Koha::Exceptions::BadParameter',
526
            'Adding a message preference with invalid message_transport_type'
527
            .' => Koha::Exceptions::BadParameter');
528
        is ($@->parameter, 'wants_digest', 'The previous exception tells us it'
529
            .' was the wants_digest');
530
        like ($@->error, qr/^Digest must be selected/, 'Exception s because of'
531
            .' digest has to be on for this transport.');
532
533
        eval {
534
            Koha::Patron::Message::Preference->new({
535
                borrowernumber => $patron->borrowernumber,
536
                message_attribute_id => -1,
537
                message_transport_types => [],
538
            })->store };
539
        is (ref $@, 'Koha::Exceptions::BadParameter',
540
            'Adding a message preference with invalid message_transport_type'
541
            .' => Koha::Exceptions::BadParameter');
542
        is ($@->parameter, 'message_attribute_id', 'The previous exception tells'
543
            .' us it was the message_attribute_id');
544
        like ($@->error, qr/^Message attribute with id -1 not found/, 'Exception '
545
            .' is because of given message attribute id is not found.');
546
547
        $schema->storage->txn_rollback;
548
    };
549
550
    subtest 'Duplicate object' => sub {
551
        plan tests => 2;
552
553
        $schema->storage->txn_begin;
554
555
        my $attribute = build_a_test_attribute();
556
        my $letter = build_a_test_letter();
557
        my $mtt = build_a_test_transport_type();
558
        Koha::Patron::Message::Transport->new({
559
            message_attribute_id   => $attribute->message_attribute_id,
560
            message_transport_type => $mtt->message_transport_type,
561
            is_digest              => 0,
562
            letter_module          => $letter->module,
563
            letter_code            => $letter->code,
564
        })->store;
565
        my $patron    = build_a_test_patron();
566
        my $preference = Koha::Patron::Message::Preference->new({
567
            borrowernumber => $patron->borrowernumber,
568
            message_attribute_id => $attribute->message_attribute_id,
569
            wants_digest => 0,
570
            days_in_advance => undef,
571
        })->store;
572
        ok($preference->borrower_message_preference_id,
573
           'Added a new messaging preference for patron.');
574
        eval { Koha::Patron::Message::Preference->new({
575
            borrowernumber => $patron->borrowernumber,
576
            message_attribute_id => $attribute->message_attribute_id,
577
            wants_digest => 0,
578
            days_in_advance => undef,
579
        })->store };
580
        is(ref $@, 'Koha::Exceptions::DuplicateObject',
581
                'Adding a duplicate preference'
582
                .' => Koha::Exceptions::DuplicateObject');
583
584
        $schema->storage->txn_rollback;
585
    };
586
};
587
588
sub build_a_test_attribute {
589
    my ($params) = @_;
590
591
    $params->{takes_days} = $params->{takes_days} && $params->{takes_days} > 0
592
                            ? 1 : 0;
593
594
    my $attribute = $builder->build({
595
        source => 'MessageAttribute',
596
        value => $params,
597
    });
598
599
    return Koha::Patron::Message::Attributes->find(
600
        $attribute->{message_attribute_id}
601
    );
602
}
603
604
sub build_a_test_category {
605
    my $categorycode   = $builder->build({
606
        source => 'Category' })->{categorycode};
607
608
    return Koha::Patron::Categories->find($categorycode);
609
}
610
611
sub build_a_test_letter {
612
    my ($params) = @_;
613
614
    my $mtt = $params->{mtt} ? $params->{mtt} : 'email';
615
    my $branchcode     = $builder->build({
616
        source => 'Branch' })->{branchcode};
617
    my $letter = $builder->build({
618
        source => 'Letter',
619
        value => {
620
            branchcode => '',
621
            is_html => 0,
622
            message_transport_type => $mtt
623
        }
624
    });
625
626
    return Koha::Notice::Templates->find({
627
        module     => $letter->{module},
628
        code       => $letter->{code},
629
        branchcode => $letter->{branchcode},
630
    });
631
}
632
633
sub build_a_test_patron {
634
    my $categorycode   = $builder->build({
635
        source => 'Category' })->{categorycode};
636
    my $branchcode     = $builder->build({
637
        source => 'Branch' })->{branchcode};
638
    my $borrowernumber = $builder->build({
639
        source => 'Borrower' })->{borrowernumber};
640
641
    return Koha::Patrons->find($borrowernumber);
642
}
643
644
sub build_a_test_transport_type {
645
    my $mtt = $builder->build({
646
        source => 'MessageTransportType' });
647
648
    return Koha::Patron::Message::Transport::Types->find(
649
        $mtt->{message_transport_type}
650
    );
651
}
652
653
sub build_a_test_category_preference {
654
    my ($params) = @_;
655
656
    my $patron = $params->{patron};
657
    my $attr = $params->{attr}
658
                    ? $params->{attr}
659
                    : build_a_test_attribute($params->{days_in_advance});
660
661
    my $letter = $params->{letter} ? $params->{letter} : build_a_test_letter();
662
    my $mtt1 = $params->{mtt1} ? $params->{mtt1} : build_a_test_transport_type();
663
    my $mtt2 = $params->{mtt2} ? $params->{mtt2} : build_a_test_transport_type();
664
665
    Koha::Patron::Message::Transport->new({
666
        message_attribute_id   => $attr->message_attribute_id,
667
        message_transport_type => $mtt1->message_transport_type,
668
        is_digest              => $params->{digest} ? 1 : 0,
669
        letter_module          => $letter->module,
670
        letter_code            => $letter->code,
671
    })->store;
672
673
    Koha::Patron::Message::Transport->new({
674
        message_attribute_id   => $attr->message_attribute_id,
675
        message_transport_type => $mtt2->message_transport_type,
676
        is_digest              => $params->{digest} ? 1 : 0,
677
        letter_module          => $letter->module,
678
        letter_code            => $letter->code,
679
    })->store;
680
681
    my $default = Koha::Patron::Message::Preference->new({
682
        categorycode         => $patron->categorycode,
683
        message_attribute_id => $attr->message_attribute_id,
684
        wants_digest         => $params->{digest} ? 1 : 0,
685
        days_in_advance      => $params->{days_in_advance}
686
                                 ? $params->{days_in_advance} : undef,
687
    })->store;
688
689
    Koha::Patron::Message::Transport::Preference->new({
690
        borrower_message_preference_id => $default->borrower_message_preference_id,
691
        message_transport_type         => $mtt1->message_transport_type,
692
    })->store;
693
    Koha::Patron::Message::Transport::Preference->new({
694
        borrower_message_preference_id => $default->borrower_message_preference_id,
695
        message_transport_type         => $mtt2->message_transport_type,
696
    })->store;
697
698
    return ($default, $mtt1, $mtt2);
699
}
700
701
sub build_a_test_complete_preference {
702
    my ($params) = @_;
703
704
    my ($default, $mtt1, $mtt2) = build_a_test_category_preference($params);
705
    my $patron = $params->{patron};
706
    $patron->set_default_messaging_preferences;
707
    return (Koha::Patron::Message::Preferences->search({
708
        borrowernumber => $patron->borrowernumber
709
    })->next, $mtt1, $mtt2);
710
}
711
712
sub mytempfile {
713
    my ( $fh, $fn ) = tempfile( SUFFIX => '.logger.test', UNLINK => 1 );
714
    print $fh $_[0]//'';
715
    close $fh;
716
    return $fn;
717
}
718
719
1;
(-)a/t/db_dependent/Koha/Patron/Message/Transport/Preferences.t (+179 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# Copyright 2017 Koha-Suomi Oy
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
20
use Modern::Perl;
21
22
use Test::More tests => 2;
23
24
use t::lib::Mocks;
25
use t::lib::TestBuilder;
26
27
use Koha::Notice::Templates;
28
use Koha::Patron::Categories;
29
use Koha::Patron::Message::Attributes;
30
use Koha::Patron::Message::Preferences;
31
use Koha::Patron::Message::Transport::Types;
32
use Koha::Patron::Message::Transports;
33
use Koha::Patrons;
34
35
my $schema  = Koha::Database->new->schema;
36
my $builder = t::lib::TestBuilder->new;
37
38
subtest 'Test class imports' => sub {
39
    plan tests => 2;
40
41
    use_ok('Koha::Patron::Message::Transport::Preference');
42
    use_ok('Koha::Patron::Message::Transport::Preferences');
43
};
44
45
subtest 'Test Koha::Patron::Message::Transport::Preferences' => sub {
46
    plan tests => 2;
47
48
    $schema->storage->txn_begin;
49
50
    my $attribute = build_a_test_attribute();
51
    my $mtt       = build_a_test_transport_type();
52
    my $letter    = build_a_test_letter({
53
        mtt => $mtt->message_transport_type
54
    });
55
    Koha::Patron::Message::Transport->new({
56
        message_attribute_id   => $attribute->message_attribute_id,
57
        message_transport_type => $mtt->message_transport_type,
58
        is_digest              => 0,
59
        letter_module          => $letter->module,
60
        letter_code            => $letter->code,
61
    })->store;
62
63
    subtest 'For a patron' => sub {
64
        my $patron    = build_a_test_patron();
65
        my $preference = Koha::Patron::Message::Preference->new({
66
            borrowernumber       => $patron->borrowernumber,
67
            message_attribute_id => $attribute->message_attribute_id,
68
            wants_digest         => 0,
69
            days_in_advance      => undef,
70
        })->store;
71
72
        my $pref_id = $preference->borrower_message_preference_id;
73
        my $transport_pref = Koha::Patron::Message::Transport::Preference->new({
74
            borrower_message_preference_id => $pref_id,
75
            message_transport_type => $mtt->message_transport_type,
76
        })->store;
77
        is(ref($transport_pref), 'Koha::Patron::Message::Transport::Preference',
78
           'Added a new messaging transport preference for patron.');
79
80
        $transport_pref->delete;
81
        is(Koha::Patron::Message::Transport::Preferences->search({
82
            borrower_message_preference_id => $pref_id,
83
            message_transport_type => $mtt->message_transport_type,
84
        })->count, 0, 'Deleted the messaging transport preference.');
85
    };
86
87
    subtest 'For a category' => sub {
88
        my $category   = build_a_test_category();
89
        my $preference = Koha::Patron::Message::Preference->new({
90
            categorycode         => $category->categorycode,
91
            message_attribute_id => $attribute->message_attribute_id,
92
            wants_digest         => 0,
93
            days_in_advance      => undef,
94
        })->store;
95
96
        my $pref_id = $preference->borrower_message_preference_id;
97
        my $transport_pref = Koha::Patron::Message::Transport::Preference->new({
98
            borrower_message_preference_id => $pref_id,
99
            message_transport_type => $mtt->message_transport_type,
100
        })->store;
101
        is(ref($transport_pref), 'Koha::Patron::Message::Transport::Preference',
102
           'Added a new messaging transport preference for category.');
103
104
        $transport_pref->delete;
105
        is(Koha::Patron::Message::Transport::Preferences->search({
106
            borrower_message_preference_id => $pref_id,
107
            message_transport_type => $mtt->message_transport_type,
108
        })->count, 0, 'Deleted the messaging transport preference.');
109
    };
110
111
    $schema->storage->txn_rollback;
112
};
113
114
sub build_a_test_attribute {
115
    my ($params) = @_;
116
117
    $params->{takes_days} = $params->{takes_days} && $params->{takes_days} > 0
118
                            ? 1 : 0;
119
120
    my $attribute = $builder->build({
121
        source => 'MessageAttribute',
122
        value => $params,
123
    });
124
125
    return Koha::Patron::Message::Attributes->find(
126
        $attribute->{message_attribute_id}
127
    );
128
}
129
130
sub build_a_test_category {
131
    my $categorycode   = $builder->build({
132
        source => 'Category' })->{categorycode};
133
134
    return Koha::Patron::Categories->find($categorycode);
135
}
136
137
sub build_a_test_letter {
138
    my ($params) = @_;
139
140
    my $mtt = $params->{mtt} ? $params->{mtt} : 'email';
141
    my $branchcode     = $builder->build({
142
        source => 'Branch' })->{branchcode};
143
    my $letter = $builder->build({
144
        source => 'Letter',
145
        value => {
146
            branchcode => '',
147
            is_html => 0,
148
            message_transport_type => $mtt
149
        }
150
    });
151
152
    return Koha::Notice::Templates->find({
153
        module => $letter->{module},
154
        code   => $letter->{code},
155
        branchcode => $letter->{branchcode},
156
    });
157
}
158
159
sub build_a_test_patron {
160
    my $categorycode   = $builder->build({
161
        source => 'Category' })->{categorycode};
162
    my $branchcode     = $builder->build({
163
        source => 'Branch' })->{branchcode};
164
    my $borrowernumber = $builder->build({
165
        source => 'Borrower' })->{borrowernumber};
166
167
    return Koha::Patrons->find($borrowernumber);
168
}
169
170
sub build_a_test_transport_type {
171
    my $mtt = $builder->build({
172
        source => 'MessageTransportType' });
173
174
    return Koha::Patron::Message::Transport::Types->find(
175
        $mtt->{message_transport_type}
176
    );
177
}
178
179
1;
(-)a/t/db_dependent/Koha/Patron/Message/Transport/Types.t (+54 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# Copyright 2017 Koha-Suomi Oy
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
20
use Modern::Perl;
21
22
use Test::More tests => 2;
23
24
use Koha::Database;
25
26
my $schema  = Koha::Database->new->schema;
27
28
subtest 'Test class imports' => sub {
29
    plan tests => 2;
30
31
    use_ok('Koha::Patron::Message::Transport::Type');
32
    use_ok('Koha::Patron::Message::Transport::Types');
33
};
34
35
subtest 'Test Koha::Patron::Message::Transport::Types' => sub {
36
    plan tests => 2;
37
38
    $schema->storage->txn_begin;
39
40
    my $transport_type = Koha::Patron::Message::Transport::Type->new({
41
        message_transport_type => 'test'
42
    })->store;
43
44
    is($transport_type->message_transport_type, 'test',
45
       'Added a new message transport type.');
46
47
    $transport_type->delete;
48
    is(Koha::Patron::Message::Transport::Types->find('test'), undef,
49
       'Deleted the message transport type.');
50
51
    $schema->storage->txn_rollback;
52
};
53
54
1;
(-)a/t/db_dependent/Koha/Patron/Message/Transports.t (-1 / +119 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/perl
2
3
# Copyright 2017 Koha-Suomi Oy
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
20
use Modern::Perl;
21
22
use Test::More tests => 2;
23
24
use t::lib::TestBuilder;
25
26
use Koha::Notice::Templates;
27
use Koha::Patron::Message::Attributes;
28
use Koha::Patron::Message::Transport::Types;
29
30
my $schema  = Koha::Database->new->schema;
31
my $builder = t::lib::TestBuilder->new;
32
33
subtest 'Test class imports' => sub {
34
    plan tests => 2;
35
36
    use_ok('Koha::Patron::Message::Transport');
37
    use_ok('Koha::Patron::Message::Transports');
38
};
39
40
subtest 'Test Koha::Patron::Message::Transports' => sub {
41
    plan tests => 2;
42
43
    $schema->storage->txn_begin;
44
45
    my $attribute = build_a_test_attribute();
46
    my $mtt       = build_a_test_transport_type();
47
    my $letter    = build_a_test_letter({
48
        mtt => $mtt->message_transport_type
49
    });
50
51
    my $transport = Koha::Patron::Message::Transport->new({
52
        message_attribute_id   => $attribute->message_attribute_id,
53
        message_transport_type => $mtt->message_transport_type,
54
        is_digest              => 0,
55
        letter_module          => $letter->module,
56
        letter_code            => $letter->code,
57
    })->store;
58
59
    is($transport->message_attribute_id, $attribute->message_attribute_id,
60
       'Added a new messaging transport.');
61
62
    $transport->delete;
63
    is(Koha::Patron::Message::Transports->search({
64
        message_attribute_id => $attribute->message_attribute_id,
65
        message_transport_type => $mtt->message_transport_type,
66
        is_digest => 0
67
    })->count, 0, 'Deleted the messaging transport.');
68
69
    $schema->storage->txn_rollback;
70
};
71
72
sub build_a_test_attribute {
73
    my ($params) = @_;
74
75
    $params->{takes_days} = $params->{takes_days} && $params->{takes_days} > 0
76
                            ? 1 : 0;
77
78
    my $attribute = $builder->build({
79
        source => 'MessageAttribute',
80
        value => $params,
81
    });
82
83
    return Koha::Patron::Message::Attributes->find(
84
        $attribute->{message_attribute_id}
85
    );
86
}
87
88
sub build_a_test_letter {
89
    my ($params) = @_;
90
91
    my $mtt = $params->{mtt} ? $params->{mtt} : 'email';
92
    my $branchcode     = $builder->build({
93
        source => 'Branch' })->{branchcode};
94
    my $letter = $builder->build({
95
        source => 'Letter',
96
        value => {
97
            branchcode => '',
98
            is_html => 0,
99
            message_transport_type => $mtt
100
        }
101
    });
102
103
    return Koha::Notice::Templates->find({
104
        module => $letter->{module},
105
        code   => $letter->{code},
106
        branchcode => $letter->{branchcode},
107
    });
108
}
109
110
sub build_a_test_transport_type {
111
    my $mtt = $builder->build({
112
        source => 'MessageTransportType' });
113
114
    return Koha::Patron::Message::Transport::Types->find(
115
        $mtt->{message_transport_type}
116
    );
117
}
118
119
1;

Return to bug 17499