From 2a118a9578c2c0fe004429810dcb3ed2653ec3bf Mon Sep 17 00:00:00 2001
From: Tomas Cohen Arazi <tomascohen@theke.io>
Date: Tue, 19 Jul 2022 14:49:52 -0300
Subject: [PATCH] Bug 30933: Add lists methods for disowning
Content-Type: text/plain; charset=utf-8

This patch aims to tidy things a bit by doing the following changes:

* Koha::Virtualshelf gets the 'transfer_ownership' method
* Koha::Virtualshelves gets the 'disown_or_delete' method
* Koha::Patron->delete gets rewritten/simplified by using
  disown_or_delete

The idea is to capture the current behavior in more fine grained
methods. So current tests should be passing as they do now.

To test:
1. Run:
   $ kshell
  k$ prove t/db_dependent/Koha/Patrons.t \
           t/db_dependent/Virtualshelves.t
=> SUCCESS: Tests pass
2. Apply this patches
3. Repeat 1
=> SUCCESS: Tests still pass!
4. Run:
  k$ prove t/db_dependent/Koha/Virtualshelf.t \
           t/db_dependent/Koha/Virtualshelves.t
=> SUCCESS: Tests pass!
5. Sign off :-D

Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
---
 Koha/Patron.pm         | 22 +---------------------
 Koha/Virtualshelf.pm   | 19 +++++++++++++++++++
 Koha/Virtualshelves.pm | 42 +++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 61 insertions(+), 22 deletions(-)

diff --git a/Koha/Patron.pm b/Koha/Patron.pm
index 4dface4de1..0a165ae0d1 100644
--- a/Koha/Patron.pm
+++ b/Koha/Patron.pm
@@ -388,17 +388,7 @@ sub delete {
             }
 
             # Handle lists (virtualshelves)
-            my $new_owner = _new_owner();
-            my $lists = $self->virtualshelves;
-            while( my $list = $lists->next ) {
-                if( $new_owner && ( $list->is_public || $list->is_shared )) {
-                    # if new_owner had a share, remove it
-                    $list->remove_share( $new_owner ) if $list->is_private;
-                    $list->set({ owner => $new_owner })->store; # transfer ownership of public/shared list
-                } else { # delete
-                    $list->delete;
-                }
-            }
+            $self->virtualshelves->disown_or_delete;
 
             # We cannot have a FK on borrower_modifications.borrowernumber, the table is also used
             # for patron selfreg
@@ -412,16 +402,6 @@ sub delete {
     return $self;
 }
 
-sub _new_owner {
-    if( C4::Context->preference('ListOwnershipUponPatronDeletion') eq 'transfer' ) {
-        # designated owner overrides userenv
-        my $designated_owner = C4::Context->preference('ListOwnerDesignated');
-        return $designated_owner if Koha::Patrons->find($designated_owner);
-        my $userenv = C4::Context->userenv;
-        return $userenv->{'number'} if $userenv;
-    }
-}
-
 =head3 category
 
 my $patron_category = $patron->category
diff --git a/Koha/Virtualshelf.pm b/Koha/Virtualshelf.pm
index 5e904e0289..382506bb28 100644
--- a/Koha/Virtualshelf.pm
+++ b/Koha/Virtualshelf.pm
@@ -23,6 +23,7 @@ use C4::Auth qw( haspermission );
 use Koha::Patrons;
 use Koha::Database;
 use Koha::DateUtils qw( dt_from_string );
+use Koha::Exceptions;
 use Koha::Exceptions::Virtualshelf;
 use Koha::Virtualshelfshare;
 use Koha::Virtualshelfshares;
@@ -331,6 +332,24 @@ sub cannot_be_transferred {
     return 0; # serving as green light
 }
 
+=head3 transfer_ownership
+
+    $list->transfer_ownership( $patron_id );
+
+This method transfers the list ownership to the passed I<$patron_id>.
+
+=cut
+
+sub transfer_ownership {
+    my ( $self, $patron_id ) = @_;
+
+    Koha::Exceptions::MissingParameter->throw( "Mandatory parameter 'patron' missing" )
+      unless $patron_id;
+
+    $self->remove_share( $patron_id ) if $self->is_private;
+    return $self->set({ owner => $patron_id })->store;
+}
+
 =head2 Internal methods
 
 =head3 _type
diff --git a/Koha/Virtualshelves.pm b/Koha/Virtualshelves.pm
index 8b40596167..d4605883a3 100644
--- a/Koha/Virtualshelves.pm
+++ b/Koha/Virtualshelves.pm
@@ -20,6 +20,7 @@ use Modern::Perl;
 
 use Koha::Database;
 
+use Koha::Patrons;
 use Koha::Virtualshelf;
 
 
@@ -31,10 +32,49 @@ Koha::Virtualshelf - Koha Virtualshelf Object class
 
 =head1 API
 
-=head2 Class Methods
+=head2 Class methods
+
+=head3 disown_or_delete
+
+    $lists->disown_or_delete;
+
+This method will transfer public/shared lists to the appropriate patron or
+just delete them if not possible.
 
 =cut
 
+sub disown_or_delete {
+    my ($self) = @_;
+
+    $self->_resultset->result_source->schema->txn_do(
+        sub {
+            if ( C4::Context->preference('ListOwnershipUponPatronDeletion') eq 'transfer' ) {
+                my $new_owner;
+
+                $new_owner = C4::Context->preference('ListOwnerDesignated')
+                  if C4::Context->preference('ListOwnerDesignated')
+                  and Koha::Patrons->find( C4::Context->preference('ListOwnerDesignated') );
+
+                unless ($new_owner) {
+                    $new_owner = C4::Context->userenv->{number};
+                }
+
+                while ( my $list = $self->next ) {
+                    if ( $list->is_public or $list->is_shared ) {
+                        $list->transfer_ownership($new_owner);
+                    } else {
+                        $list->delete;
+                    }
+                }
+            } else {    # 'delete'
+                $_->delete for $self->as_list;
+            }
+        }
+    );
+
+    return $self;
+}
+
 =head3 get_private_shelves
 
 =cut
-- 
2.20.1