From 6020720fc27c7493b46948ff1a94b0a011424fb4 Mon Sep 17 00:00:00 2001
From: Kyle M Hall <kyle@bywatersolutions.com>
Date: Mon, 21 Jul 2014 11:49:40 -0400
Subject: [PATCH] Bug 9303 [3] - relative's checkouts in the opac

Signed-off-by: Nick Clemens <nick@quecheelibrary.org>
---
 C4/Members.pm                                      |    1 -
 C4/Reserves.pm                                     |    1 +
 Koha/Schema/Result/Borrower.pm                     |    6 ++-
 Koha/Template/Plugin/Koha.pm                       |   15 ++++++
 .../prog/en/modules/admin/preferences/opac.pref    |    7 +++
 .../prog/en/modules/admin/preferences/patrons.pref |    6 ++
 .../prog/en/modules/members/memberentrygen.tt      |   16 ++++++
 .../prog/en/modules/members/moremember.tt          |   10 ++++
 .../bootstrap/en/modules/opac-memberentry.tt       |   43 ++++++++++++++++
 .../opac-tmpl/bootstrap/en/modules/opac-privacy.tt |   24 ++++++++-
 .../opac-tmpl/bootstrap/en/modules/opac-user.tt    |   54 ++++++++++++++++++-
 members/moremember.pl                              |    1 +
 opac/opac-privacy.pl                               |   38 +++++++++-----
 opac/opac-user.pl                                  |   32 ++++++++---
 14 files changed, 224 insertions(+), 30 deletions(-)

diff --git a/C4/Members.pm b/C4/Members.pm
index 6f95b94..8f41be3 100644
--- a/C4/Members.pm
+++ b/C4/Members.pm
@@ -115,7 +115,6 @@ BEGIN {
     push @EXPORT, qw(
         &ModMember
         &changepassword
-         &ModPrivacy
     );
 
     #Delete data
diff --git a/C4/Reserves.pm b/C4/Reserves.pm
index a188f96..c8c3321 100644
--- a/C4/Reserves.pm
+++ b/C4/Reserves.pm
@@ -266,6 +266,7 @@ sub GetReserve {
     my ($reserve_id) = @_;
 
     my $dbh = C4::Context->dbh;
+
     my $query = "SELECT * FROM reserves WHERE reserve_id = ?";
     my $sth = $dbh->prepare( $query );
     $sth->execute( $reserve_id );
diff --git a/Koha/Schema/Result/Borrower.pm b/Koha/Schema/Result/Borrower.pm
index 2a22053..894d19e 100644
--- a/Koha/Schema/Result/Borrower.pm
+++ b/Koha/Schema/Result/Borrower.pm
@@ -1140,6 +1140,10 @@ __PACKAGE__->many_to_many("courses", "course_instructors", "course");
 # Created by DBIx::Class::Schema::Loader v0.07040 @ 2014-12-21 23:11:08
 # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:49MbDhILto8NukjDlkt8sA
 
+__PACKAGE__->belongs_to(
+    "guarantor",
+    "Koha::Schema::Result::Borrower",
+    { borrowernumber => "guarantorid" },
+);
 
-# You can replace this text with custom content, and it will be preserved on regeneration
 1;
diff --git a/Koha/Template/Plugin/Koha.pm b/Koha/Template/Plugin/Koha.pm
index f5898b5..410d636 100644
--- a/Koha/Template/Plugin/Koha.pm
+++ b/Koha/Template/Plugin/Koha.pm
@@ -23,6 +23,7 @@ use Encode qw( encode );
 use base qw( Template::Plugin );
 
 use C4::Context;
+use Koha::Database;
 
 =pod
 
@@ -59,4 +60,18 @@ sub Version {
     };
 }
 
+sub Find {
+    my ( $self, $rs, $id ) = @_;
+
+    return unless ( $rs && $id );
+
+    my $resultset = Koha::Database->new()->schema()->resultset($rs);
+
+    return unless $resultset;
+
+    my $row = $resultset->find($id);
+
+    return $row;
+}
+
 1;
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref
index f0c0951..0a4d84f 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref
@@ -588,6 +588,13 @@ OPAC:
                   no: "Don't allow"
             - patrons to choose their own privacy settings for their reading history.  This requires opacreadinghistory and AnonymousPatron
         -
+            - pref: AllowPatronToSetCheckoutsVisibilityForGuarantor
+              default: 0
+              choices:
+                  yes: Allow
+                  no: "Don't allow"
+            - patrons to choose their own privacy settings for showing the patron's checkouts to the patron's guarantor".
+        -
             - Use borrowernumber
             - pref: AnonymousPatron
               class: integer
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
index aa567c3..0d80a3f 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref
@@ -135,6 +135,12 @@ Patrons:
                no: "Don't"
          - enable the ability to upload and attach arbitrary files to a borrower record.
      -
+         - pref: AllowStaffToSetCheckoutsVisibilityForGuarantor
+           choices:
+               yes: Allow
+               no: "Don't allow"
+         - staff to set the ability for a patron's checkouts to be viewed by linked patrons in the OPAC.
+     -
          - Card numbers for patrons must be
          - pref: CardnumberLength
          - "characters long. The length can be a single number to specify an exact length, a range separated by a comma (i.e., 'Min,Max'), or a maximum with no minimum (i.e., ',Max')."
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt
index 95f42e6..6a19f48 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt
@@ -1,5 +1,6 @@
 [% USE Koha %]
 [% USE KohaDates %]
+[% USE Koha %]
 [% INCLUDE 'doc-head-open.inc' %]
 <title>Koha &rsaquo; Patrons &rsaquo; 
 [% IF ( opadd ) %]Add[% ELSIF ( opduplicate ) %]Duplicate[% ELSE %] Modify[% END %] [% IF ( categoryname ) %] [% categoryname %] patron[% ELSE %][% IF ( I ) %] Organization patron[% END %][% IF ( A ) %] Adult patron[% END %][% IF ( C ) %] Child patron[% END %][% IF ( P ) %] Professional patron[% END %][% IF ( S ) %] Staff patron[% END %][% END %][% UNLESS ( opadd ) %] [% surname %], [% firstname %][% END %]</title>
@@ -1185,6 +1186,21 @@
 			[% END %]
 	  [% IF ( mandatorypassword ) %]<span class="required">Required</span>[% END %][% IF ( ERROR_password_mismatch ) %]<span class="required">Passwords do not match</span>[% END %]
 		</li>
+        [% IF guarantorid && Koha.Preference('AllowStaffToSetCheckoutsVisibilityForGuarantor') %]
+            <li>
+                <label for="privacy_guarantor_checkouts">Show checkouts to guarantor</label>
+                <select name="privacy_guarantor_checkouts" id="privacy_guarantor_checkouts">
+                    [% IF privacy_guarantor_checkouts %]
+                        <option value="0">No</option>
+                        <option value="1" selected>Yes</option>
+                    [% ELSE %]
+                        <option value="0" selected>No</option>
+                        <option value="1">Yes</option>
+                    [% END %]
+                </select>
+                <div class="hint">Allow guarantor of this patron to view this patron's checkouts from the OPAC</div>
+            </li>
+        [% END %]
 		</ol>
 		</fieldset>
         [% END # hide fieldset %][% END %]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt
index 8ebd31f..ca27d74 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt
@@ -347,6 +347,16 @@ function validate1(date) {
          [% IF ( privacy1 ) %]Default[% END %]
          [% IF ( privacy2 ) %]Never[% END %]
     </li>[% END %]
+
+    <li>
+        <span class="label">Show checkouts to guarantor</span>
+        [% IF privacy_guarantor_checkouts %]
+            Yes
+        [% ELSE %]
+            No
+        [% END %]
+    </li>
+
     [% IF ( sort1 ) %]<li><span class="label">Sort field 1:</span>[% lib1 %]</li>[% END %]
     [% IF ( sort2 ) %]<li><span class="label">Sort field 2:</span>[% lib2 %]</li>[% END %]
     <li><span class="label">Username: </span>[% userid %]</li>
diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-memberentry.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-memberentry.tt
index bbca649..a7f6160 100644
--- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-memberentry.tt
+++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-memberentry.tt
@@ -54,6 +54,33 @@
                     <div class="alert">You typed in the wrong characters in the box before submitting. Please try again.</div>
                 [% END %]
 
+                [% IF borrower.guarantorid && !Koha.Preference('OPACPrivacy') && Koha.Preference('AllowPatronToSetCheckoutsVisibilityForGuarantor') %]
+                    <fieldset class="rows" id="memberentry_privacy">
+                        <legend id="privacy_legend">Privacy</legend>
+                        <ol>
+                            <li>
+                                <label>Allow your guarantor to view your current checkouts?</label>
+                                <select id="privacy_guarantor_checkouts">
+                                    <option value="0">No</option>
+                                    [% IF borrower.privacy_guarantor_checkouts %]
+                                        <option value="1" selected="selected">Yes</option>
+                                    [% ELSE %]
+                                        <option value="1">Yes</option>
+                                    [% END %]
+                                </select>
+                                <span class="hint">
+                                    <a id="update_privacy_guarantor_checkouts" href="#" class="btn">Update</a>
+                                    <span id="update_privacy_guarantor_checkouts_message" class="alert" style="display:none"></span>
+                                </span>
+                                <span class="hint">
+                                    [% SET g = Koha.Find('Borrower',borrower.guarantorid) %]
+                                    Your guarantor is <i>[% g.firstname %] [% g.surname %]</i>
+                                </span>
+                            </li>
+                        </ol>
+                    </fieldset>
+                [% END %]
+
                 <form method="post" action="/cgi-bin/koha/opac-memberentry.pl" id="memberentry-form">
 
                 [% UNLESS hidden.defined('branchcode') %]
@@ -796,6 +823,22 @@
             [% ELSE %]
                 $( "#borrower_dateofbirth" ).datepicker({ yearRange: "c-120:c" });
             [% END %]
+
+            [% IF borrower.guarantorid && !Koha.Preference('OPACPrivacy') && Koha.Preference('AllowPatronToSetCheckoutsVisibilityForGuarantor') %]
+                $('#update_privacy_guarantor_checkouts').click( function() {
+                    $.post( "/cgi-bin/koha/svc/patron/show_checkouts_to_relatives", { privacy_guarantor_checkouts: $('#privacy_guarantor_checkouts').val() })
+                     .done(function( data ) {
+                         var message;
+                         if ( data.success ) {
+                             message = _("Your setting has been updated!");
+                         } else {
+                             message = _("Unable to update your setting!");
+                         }
+
+                         $('#update_privacy_guarantor_checkouts_message').fadeIn("slow").text( message ).delay( 5000 ).fadeOut("slow");
+                     });
+                });
+            [% END %]
         });
     //]]>
     </script>
diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-privacy.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-privacy.tt
index 7686000..6fc0c31 100644
--- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-privacy.tt
+++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-privacy.tt
@@ -48,7 +48,7 @@
                                 <input type="hidden" name="op" value="update_privacy" />
                                     <fieldset>
                                     <label for="privacy">Please choose your privacy rule:</label>
-                                    <div class="input-append">
+                                    <div>
                                         <select name="privacy" id="privacy">
                                             [% IF ( privacy0 ) %]
                                                 <option value="0" selected="selected" class="privacy0">Forever</option>
@@ -66,8 +66,28 @@
                                                 <option value="2" class="privacy2">Never</option>
                                             [% END %]
                                         </select>
-                                        <button type="Submit" class="btn">Submit</button>
                                     </div>
+
+                                    [% SET b = Koha.Find('Borrower', borrower.borrowernumber) %]
+                                    [% IF b.guarantorid && Koha.Preference('AllowPatronToSetCheckoutsVisibilityForGuarantor') %]
+                                        <div>
+                                            <label for="privacy_guarantor_checkouts">Allow your guarantor to view your current checkouts?</label>
+                                            <select name="privacy_guarantor_checkouts">
+                                                [% IF borrower.privacy_guarantor_checkouts %]
+                                                    <option value="0">No</option>
+                                                    <option value="1" selected>Yes</option>
+                                                [% ELSE %]
+                                                    <option value="0" selected>No</option>
+                                                    <option value="1">Yes</option>
+                                                [% END %]
+                                            </select>
+                                            <span class="hint">
+                                                Your guarantor is <i>[% b.guarantor.firstname %] [% b.guarantor.surname %]</i>
+                                            </span>
+                                        </div>
+                                    [% END %]
+
+                                    <button type="Submit" class="btn">Save</button>
                                 </fieldset>
                             </form>
                         <h2>Immediate deletion</h2>
diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-user.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-user.tt
index f4cbddb..61e565f 100644
--- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-user.tt
+++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-user.tt
@@ -1,5 +1,6 @@
 [% USE Koha %]
 [% USE KohaDates %]
+[% USE EncodeUTF8 %]
 
 [% INCLUDE 'doc-head-open.inc' %]
 [% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha online[% END %] catalog &rsaquo; Your library home
@@ -104,6 +105,7 @@
                     <div id="opac-user-views" class="toptabs">
                         <ul>
                             <li><a href="#opac-user-checkouts">Checked out ([% issues_count %])</a></li>
+                            [% IF relatives %]<li><a href="#opac-user-relative-issues">Relatives' checkouts</a></li>[% END %]
                             [% IF ( overdues_count ) %]<li><a href="#opac-user-overdues">Overdue ([% overdues_count %])</a></li>[% END %]
                             [% IF ( OPACFinesTab ) %]
                                 [% IF ( BORROWER_INF.amountoverfive ) %]<li><a href="#opac-user-fines">Fines ([% BORROWER_INF.amountoutstanding %])</a></li>[% END %]
@@ -132,7 +134,7 @@
                                                 [% IF ( show_barcode ) %]
                                                     <th>Barcode</th>
                                                 [% END %]
-                                                    <th>Call No.</th>
+                                                    <th>Call number</th>
                                                 [% IF ( OpacRenewalAllowed && !( borrower.is_expired && borrower.BlockExpiredPatronOpacActions ) ) %]
                                                     <th class="nosort">Renew</th>
                                                 [% END %]
@@ -365,6 +367,51 @@
                             </div> <!-- /#opac-user-waiting -->
                         [% END # waiting_count && atdestination %]
 
+                        [% IF relatives %]
+                            <div id="opac-user-relative-issues">
+                                <table id="opac-user-relative-issues-table" class="table table-bordered table-striped">
+                                    <thead>
+                                        <tr>
+                                            <th class="anti-the">Title</th>
+                                            <th>Due</th>
+                                            <th>Barcode</th>
+                                            <th>Call number</th>
+                                            <th class="psort">Relative</th>
+                                        </tr>
+                                    </thead>
+
+                                    <tbody>
+                                        [% FOREACH r IN relatives %]
+                                            [% FOREACH i IN r.issues %]
+                                                <tr>
+                                                    <td>
+                                                        <a href="/cgi-bin/koha/opac-detail.pl?biblionumber=[% i.item.biblio.biblionumber %]">
+                                                            [% i.item.biblio.title | $EncodeUTF8 %]
+                                                        </a>
+                                                    </td>
+
+                                                    <td>
+                                                        [% i.date_due | $KohaDates %]
+                                                    </td>
+
+                                                    <td>
+                                                        [% i.item.barcode %]
+                                                    </td>
+
+                                                    <td>
+                                                        [% i.item.itemcallnumber | $EncodeUTF8 %]
+                                                    </td>
+
+                                                    <td>
+                                                        [% r.firstname | $EncodeUTF8 %] [% r.surname | $EncodeUTF8 %]
+                                                    </td>
+                                                </tr>
+                                            [% END %]
+                                        [% END %]
+                                    </tbody>
+                                </table>
+                            </div>
+                        [% END %]
 
                         [% IF ( overdues_count ) %]
                             <div id="opac-user-overdues">
@@ -377,7 +424,7 @@
                                             <th class="anti-the">Title</th>
                                             [% UNLESS ( item_level_itypes ) %]<th>Item type</th> [% END %]
                                             [% IF ( show_barcode ) %]<th>Barcode</th>[% END %]
-                                            <th>Call no.</th>
+                                            <th>Call number</th>
                                             <th class="title-string psort">Due</th>
                                             [% IF ( OpacRenewalAllowed ) %]
                                                 <th class="nosort">Renew</th>
@@ -686,7 +733,8 @@
             $(".js-hide").hide();
             $(".modal-nojs").addClass("modal").addClass("hide").removeClass("modal-nojs");
             $(".suspend-until").prop("readonly",1);
-            var dTables = $("#checkoutst,#holdst,#overduest");
+
+            var dTables = $("#checkoutst,#holdst,#overduest,#opac-user-relative-issues-table");
             dTables.each(function(){
                 var thIndex = $(this).find("th.psort").index();
                 $(this).dataTable($.extend(true, {}, dataTablesDefaults, {
diff --git a/members/moremember.pl b/members/moremember.pl
index 92fe2d9..6ae8d6c 100755
--- a/members/moremember.pl
+++ b/members/moremember.pl
@@ -376,6 +376,7 @@ $template->param(
     is_child        => ($category_type eq 'C'),
     samebranch     => $samebranch,
     quickslip		  => $quickslip,
+    privacy_guarantor_checkouts => $data->{'privacy_guarantor_checkouts'},
     activeBorrowerRelationship => (C4::Context->preference('borrowerRelationship') ne ''),
     AutoResumeSuspendedHolds => C4::Context->preference('AutoResumeSuspendedHolds'),
     SuspendHoldsIntranet => C4::Context->preference('SuspendHoldsIntranet'),
diff --git a/opac/opac-privacy.pl b/opac/opac-privacy.pl
index 4d611a3..9e3abf0 100755
--- a/opac/opac-privacy.pl
+++ b/opac/opac-privacy.pl
@@ -47,18 +47,25 @@ my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
     }
 );
 
-my $op = $query->param("op");
-my $privacy = $query->param("privacy");
+my $op                         = $query->param("op");
+my $privacy                    = $query->param("privacy");
+my $privacy_guarantor_checkouts = $query->param("privacy_guarantor_checkouts");
 
-if ($op eq "update_privacy")
-{
-    ModPrivacy($borrowernumber,$privacy);
-    $template->param('privacy_updated' => 1);
+if ( $op eq "update_privacy" ) {
+    ModMember(
+        borrowernumber             => $borrowernumber,
+        privacy                    => $privacy,
+        privacy_guarantor_checkouts => $privacy_guarantor_checkouts,
+    );
+    $template->param( 'privacy_updated' => 1 );
 }
-if ($op eq "delete_record") {
+elsif ( $op eq "delete_record" ) {
+
     # delete all reading records for items returned
     # uses a hardcoded date ridiculously far in the future
-    my ($rows,$err_history_not_deleted) = AnonymiseIssueHistory('2999-12-12',$borrowernumber);
+    my ( $rows, $err_history_not_deleted ) =
+      AnonymiseIssueHistory( '2999-12-12', $borrowernumber );
+
     # confirm the user the deletion has been done
     if ( !$err_history_not_deleted ) {
         $template->param( 'deleted' => 1 );
@@ -67,14 +74,17 @@ if ($op eq "delete_record") {
         $template->param( 'err_history_not_deleted' => 1 );
     }
 }
+
 # get borrower privacy ....
-my ( $borr ) = GetMemberDetails( $borrowernumber );
+my $borrower = GetMemberDetails( $borrowernumber );
 
-$template->param( 'Ask_data'       => '1',
-                    'privacy'.$borr->{'privacy'} => 1,
-                    'firstname' => $borr->{'firstname'},
-                    'surname' => $borr->{'surname'},
-                    'privacyview' => 1,
+$template->param(
+    'Ask_data'                         => 1,
+    'privacy' . $borrower->{'privacy'} => 1,
+    'privacyview'                      => 1,
+    'borrower'                         => $borrower,
+    'surname'                          => $borrower->{surname},
+    'firstname'                        => $borrower->{firstname},
 );
 
 output_html_with_http_headers $query, $cookie, $template->output;
diff --git a/opac/opac-user.pl b/opac/opac-user.pl
index 995db7b..6f1e4af 100755
--- a/opac/opac-user.pl
+++ b/opac/opac-user.pl
@@ -36,6 +36,7 @@ use C4::Letters;
 use C4::Branch; # GetBranches
 use Koha::DateUtils;
 use Koha::Borrower::Debarments qw(IsDebarred);
+use Koha::Database;
 
 use constant ATTRIBUTE_SHOW_BARCODE => 'SHOW_BCODE';
 
@@ -382,18 +383,31 @@ if ( $borr->{'opacnote'} ) {
   );
 }
 
+if (   C4::Context->preference('AllowPatronToSetCheckoutsVisibilityForGuarantor')
+    || C4::Context->preference('AllowStaffToSetCheckoutsVisibilityForGuarantor') )
+{
+    my @relatives =
+      Koha::Database->new()->schema()->resultset("Borrower")->search(
+        {
+            privacy_guarantor_checkouts => 1,
+            'me.guarantorid'           => $borrowernumber
+        },
+        { prefetch => [ { 'issues' => { 'item' => 'biblio' } } ] }
+      );
+    $template->param( relatives => \@relatives );
+}
+
 $template->param(
-    bor_messages_loop    => GetMessages( $borrowernumber, 'B', 'NONE' ),
+    borrower           => $borr,
+    bor_messages_loop  => GetMessages( $borrowernumber, 'B', 'NONE' ),
     waiting_count      => $wcount,
-    patronupdate => $patronupdate,
+    patronupdate       => $patronupdate,
     OpacRenewalAllowed => C4::Context->preference("OpacRenewalAllowed"),
-    userview => 1,
-);
-
-$template->param(
-    SuspendHoldsOpac => C4::Context->preference('SuspendHoldsOpac'),
-    AutoResumeSuspendedHolds => C4::Context->preference('AutoResumeSuspendedHolds'),
-    OpacHoldNotes => C4::Context->preference('OpacHoldNotes'),
+    userview           => 1,
+    SuspendHoldsOpac   => C4::Context->preference('SuspendHoldsOpac'),
+    OpacHoldNotes      => C4::Context->preference('OpacHoldNotes'),
+    AutoResumeSuspendedHolds =>
+      C4::Context->preference('AutoResumeSuspendedHolds'),
 );
 
 output_html_with_http_headers $query, $cookie, $template->output;
-- 
1.7.2.5