From 63f5fb66d124b4ca239e57fbbf69d3d1c0a82f4a Mon Sep 17 00:00:00 2001
From: Tomas Cohen Arazi <tomascohen@theke.io>
Date: Fri, 21 Jun 2019 17:10:23 -0300
Subject: [PATCH] Bug 22709: Add after biblio/item action hooks

This patch introduces after-action hooks for
- C4::Biblio::{Add|Mod|Del}Biblio
- C4::Items::{Add|Mod|Del}Biblio

After the action has taken place, a call to a helper method is done,
which loops through all plugins implementing the hooks, and calls the
plugin method. The related object is passed, along with an 'action'
string specifying the action that took place, and the object id (which
is specially important for the 'Del' case).

To test:
- Apply this patchset
- Run:
  $ kshell
 k$ prove t/db_dependent/Biblio_and_Items_plugin_hooks.t
=> SUCCESS: Tests pass!
- Sign off :-D

Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
---
 C4/Biblio.pm | 43 +++++++++++++++++++++++++++++++++++++++++++
 C4/Items.pm  | 40 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 83 insertions(+)

diff --git a/C4/Biblio.pm b/C4/Biblio.pm
index 958f7d9753..8baeaff281 100644
--- a/C4/Biblio.pm
+++ b/C4/Biblio.pm
@@ -79,6 +79,7 @@ BEGIN {
 }
 
 use Carp;
+use Try::Tiny;
 
 use Encode qw( decode is_utf8 );
 use List::MoreUtils qw( uniq );
@@ -103,6 +104,7 @@ use Koha::Acquisition::Currencies;
 use Koha::Biblio::Metadatas;
 use Koha::Holds;
 use Koha::ItemTypes;
+use Koha::Plugins;
 use Koha::SearchEngine;
 use Koha::Libraries;
 use Koha::Util::MARC;
@@ -233,6 +235,8 @@ sub AddBiblio {
         C4::OAI::Sets::UpdateOAISetsBiblio($biblionumber, $record);
     }
 
+    _after_biblio_action_hooks({ action => 'create', biblio_id => $biblionumber });
+
     logaction( "CATALOGUING", "ADD", $biblionumber, "biblio" ) if C4::Context->preference("CataloguingLog");
     return ( $biblionumber, $biblioitemnumber );
 }
@@ -318,6 +322,8 @@ sub ModBiblio {
     _koha_modify_biblio( $dbh, $oldbiblio, $frameworkcode );
     _koha_modify_biblioitem_nonmarc( $dbh, $oldbiblio );
 
+    _after_biblio_action_hooks({ action => 'modify', biblio_id => $biblionumber });
+
     # update OAI-PMH sets
     if(C4::Context->preference("OAI-PMH:AutoUpdateSets")) {
         C4::OAI::Sets::UpdateOAISetsBiblio($biblionumber, $record);
@@ -418,6 +424,8 @@ sub DelBiblio {
     # from being generated by _koha_delete_biblioitems
     $error = _koha_delete_biblio( $dbh, $biblionumber );
 
+    _after_biblio_action_hooks({ action => 'delete', biblio_id => $biblionumber });
+
     logaction( "CATALOGUING", "DELETE", $biblionumber, "biblio" ) if C4::Context->preference("CataloguingLog");
 
     return;
@@ -3184,6 +3192,7 @@ sub ModBiblioMarc {
     $m_rs->store;
 
     ModZebra( $biblionumber, "specialUpdate", "biblioserver" );
+
     return $biblionumber;
 }
 
@@ -3440,6 +3449,40 @@ sub RemoveAllNsb {
 1;
 
 
+=head2 _after_biblio_action_hooks
+
+Helper method that takes care of calling all plugin hooks
+
+=cut
+
+sub _after_biblio_action_hooks {
+    my ( $args ) = @_;
+
+    my $biblio_id = $args->{biblio_id};
+    my $action    = $args->{action};
+
+    if ( C4::Context->preference('UseKohaPlugins') && C4::Context->config("enable_plugins") ) {
+
+        my @plugins = Koha::Plugins->new->GetPlugins({
+            method => 'after_biblio_action',
+        });
+
+        if (@plugins) {
+
+            my $biblio = Koha::Biblios->find( $biblio_id );
+
+            foreach my $plugin ( @plugins ) {
+                try {
+                    $plugin->after_biblio_action({ action => $action, biblio => $biblio, biblio_id => $biblio_id });
+                }
+                catch {
+                    warn "$_";
+                };
+            }
+        }
+    }
+}
+
 __END__
 
 =head1 AUTHOR
diff --git a/C4/Items.pm b/C4/Items.pm
index 15b61f0005..ab00a4c2a6 100644
--- a/C4/Items.pm
+++ b/C4/Items.pm
@@ -55,6 +55,7 @@ BEGIN {
 }
 
 use Carp;
+use Try::Tiny;
 use C4::Context;
 use C4::Koha;
 use C4::Biblio;
@@ -224,6 +225,8 @@ sub AddItem {
     logaction( "CATALOGUING", "ADD", $itemnumber, "item" )
       if C4::Context->preference("CataloguingLog");
 
+    _after_item_action_hooks({ action => 'create', item_id => $itemnumber });
+
     return ( $item->{biblionumber}, $item->{biblioitemnumber}, $itemnumber );
 }
 
@@ -529,6 +532,8 @@ sub ModItem {
     # item status is possible
     ModZebra( $biblionumber, "specialUpdate", "biblioserver" );
 
+    _after_item_action_hooks({ action => 'modify', item_id => $itemnumber });
+
     logaction( "CATALOGUING", "MODIFY", $itemnumber, "item " . Dumper($item) )
       if $log_action && C4::Context->preference("CataloguingLog");
 }
@@ -613,6 +618,8 @@ sub DelItem {
 
     ModZebra( $biblionumber, "specialUpdate", "biblioserver" );
 
+    _after_item_action_hooks({ action => 'delete', item_id => $itemnumber });
+
     #search item field code
     logaction("CATALOGUING", "DELETE", $itemnumber, "item") if C4::Context->preference("CataloguingLog");
     return $deleted;
@@ -2638,5 +2645,38 @@ sub ToggleNewStatus {
     return $report;
 }
 
+=head2 _after_item_action_hooks
+
+Helper method that takes care of calling all plugin hooks
+
+=cut
+
+sub _after_item_action_hooks {
+    my ( $args ) = @_;
+
+    my $item_id = $args->{item_id};
+    my $action  = $args->{action};
+
+    if ( C4::Context->preference('UseKohaPlugins') && C4::Context->config("enable_plugins") ) {
+
+        my @plugins = Koha::Plugins->new->GetPlugins({
+            method => 'after_item_action',
+        });
+
+        if (@plugins) {
+
+            my $item = Koha::Items->find( $item_id );
+
+            foreach my $plugin ( @plugins ) {
+                try {
+                    $plugin->after_item_action({ action => $action, item => $item, item_id => $item_id });
+                }
+                catch {
+                    warn "$_";
+                };
+            }
+        }
+    }
+}
 
 1;
-- 
2.20.1 (Apple Git-117)