From 13e9835fe9a2e376dffec2bf27c99827f7a69d6f Mon Sep 17 00:00:00 2001
From: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
Date: Wed, 13 Dec 2023 15:12:30 +0000
Subject: [PATCH] Bug 35536: Add Koha::Plugins->RemovePlugins class method
Test plan:
Run t/db_dependent/Koha/Plugins/Plugins.t
Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
---
Koha/Plugins.pm | 42 ++++++++++++
t/db_dependent/Koha/Plugins/Plugins.t | 93 ++++++++++++++++++++++++++-
2 files changed, 132 insertions(+), 3 deletions(-)
diff --git a/Koha/Plugins.pm b/Koha/Plugins.pm
index 72ae308f3ff..3f2bed21965 100644
--- a/Koha/Plugins.pm
+++ b/Koha/Plugins.pm
@@ -32,6 +32,7 @@ use C4::Output;
use Koha::Cache::Memory::Lite;
use Koha::Exceptions::Plugin;
+use Koha::Plugins::Datas;
use Koha::Plugins::Methods;
use constant ENABLED_PLUGINS_CACHE_KEY => 'enabled_plugins';
@@ -306,6 +307,47 @@ sub InstallPlugins {
return @plugins;
}
+=head2 RemovePlugins
+
+ Koha::Plugins->RemovePlugins( {
+ [ plugin_class => MODULE_NAME, destructive => 1, disable => 1 ],
+ } );
+
+ This is primarily for unit testing. Take care when you pass the
+ destructive flag (know what you are doing)!
+
+ The method removes records from plugin_methods for one or all plugins.
+
+ If you pass the destructive flag, it will remove records too from
+ plugin_data for one or all plugins. Destructive overrules disable.
+
+ If you pass disable, it will disable one or all plugins (in plugin_data).
+
+ If you do not pass destructive or disable, this method does not touch
+ records in plugin_data. The cache key for enabled plugins will be cleared
+ only if you pass disabled or destructive.
+
+=cut
+
+sub RemovePlugins {
+ my ( $class, $params ) = @_;
+
+ my $cond = {
+ $params->{plugin_class}
+ ? ( plugin_class => $params->{plugin_class} )
+ : ()
+ };
+ Koha::Plugins::Methods->search($cond)->delete;
+ if ( $params->{destructive} ) {
+ Koha::Plugins::Datas->search($cond)->delete;
+ Koha::Cache::Memory::Lite->clear_from_cache( Koha::Plugins->ENABLED_PLUGINS_CACHE_KEY );
+ } elsif ( $params->{disable} ) {
+ $cond->{plugin_key} = '__ENABLED__';
+ Koha::Plugins::Datas->search($cond)->update( { plugin_value => 0 } );
+ Koha::Cache::Memory::Lite->clear_from_cache( Koha::Plugins->ENABLED_PLUGINS_CACHE_KEY );
+ }
+}
+
1;
__END__
diff --git a/t/db_dependent/Koha/Plugins/Plugins.t b/t/db_dependent/Koha/Plugins/Plugins.t
index 71497a30363..3037ed801e4 100755
--- a/t/db_dependent/Koha/Plugins/Plugins.t
+++ b/t/db_dependent/Koha/Plugins/Plugins.t
@@ -24,11 +24,13 @@ use File::Temp qw( tempdir tempfile );
use FindBin qw($Bin);
use Module::Load::Conditional qw(can_load);
use Test::MockModule;
-use Test::More tests => 16;
+use Test::More tests => 17;
use Test::Warn;
use C4::Context;
+use Koha::Cache::Memory::Lite;
use Koha::Database;
+use Koha::Plugins::Datas;
use Koha::Plugins::Methods;
use t::lib::Mocks;
@@ -323,7 +325,92 @@ subtest 'Koha::Plugin::Test' => sub {
$schema->storage->txn_rollback;
};
-$schema->storage->txn_begin; # matching rollback at the very end
+subtest 'RemovePlugins' => sub {
+ plan tests => 3;
+
+ $schema->storage->txn_begin;
+ t::lib::Mocks::mock_config( 'enable_plugins', 1 );
+
+ our $class_basename = 'Koha::Plugin::TestMR::' . time;
+
+ sub reload_plugin {
+ my ( $i, $mocks ) = @_;
+ Koha::Plugins::Data->new(
+ { plugin_class => "$class_basename$i", plugin_key => '__ENABLED__', plugin_value => 1 } )->store;
+ Koha::Plugins::Method->new( { plugin_class => "$class_basename$i", plugin_method => "testmr$i" } )->store;
+
+ # no_auto => 1 here prevents loading of a not-existing module
+ $mocks->[$i] = Test::MockModule->new( "$class_basename$i", no_auto => 1 )->mock( new => 1 )
+ unless $mocks->[$i];
+ }
+
+ # We will (re)create new plugins (without modules)
+ # This requires mocking can_load from Module::Load::Conditional
+ my $mlc_mock = Test::MockModule->new('Koha::Plugins')->mock( can_load => 1 );
+ my $plugin_mocks = [];
+ my @enabled_plugins;
+
+ subtest 'Destructive flag' => sub {
+ reload_plugin( $_, $plugin_mocks ) for 1 .. 3;
+ Koha::Plugins->RemovePlugins( { destructive => 1 } );
+ is( Koha::Plugins::Datas->count, 0, 'No data in plugin_data' );
+ is( Koha::Plugins::Methods->count, 0, 'No data in plugin_methods' );
+ @enabled_plugins = Koha::Plugins->get_enabled_plugins; # testing if cache cleared
+ is( scalar @enabled_plugins, 0, 'No enabled plugins' );
+
+ reload_plugin( $_, $plugin_mocks ) for 1 .. 3;
+ Koha::Plugins->RemovePlugins( { plugin_class => "${class_basename}2", destructive => 1 } );
+ is( Koha::Plugins::Datas->count, 2, '2 in plugin_data' );
+ is( Koha::Plugins::Methods->count, 2, '2 in plugin_methods' );
+ @enabled_plugins = Koha::Plugins->get_enabled_plugins;
+ is( scalar @enabled_plugins, 2, '2 enabled plugins' );
+ Koha::Plugins->RemovePlugins( { destructive => 1 } );
+ };
+
+ subtest 'Disable flag' => sub {
+ reload_plugin( $_, $plugin_mocks ) for 1 .. 4;
+ Koha::Plugins->RemovePlugins( { disable => 1 } );
+ is( Koha::Plugins::Datas->count, 4, '4 in plugin_data' );
+ is( Koha::Plugins::Methods->count, 0, 'No data in plugin_methods' );
+ @enabled_plugins = Koha::Plugins->get_enabled_plugins;
+ is( scalar @enabled_plugins, 0, '0 enabled plugins' );
+
+ reload_plugin( $_, $plugin_mocks ) for 5 .. 6;
+ Koha::Plugins->RemovePlugins( { plugin_class => "${class_basename}5", disable => 1 } );
+ is( Koha::Plugins::Datas->count, 6, '6 in plugin_data' );
+ is( Koha::Plugins::Methods->count, 1, '1 in plugin_methods' );
+ @enabled_plugins = Koha::Plugins->get_enabled_plugins;
+ is( scalar @enabled_plugins, 1, '1 enabled plugins' );
+ Koha::Plugins->RemovePlugins( { destructive => 1 } );
+ };
+
+ subtest 'No flags' => sub {
+ reload_plugin( $_, $plugin_mocks ) for 1 .. 2;
+ Koha::Plugins->RemovePlugins;
+ is( Koha::Plugins::Datas->count, 2, '2 in plugin_data' );
+ is( Koha::Plugins::Methods->count, 0, 'No data in plugin_methods' );
+ @enabled_plugins = Koha::Plugins->get_enabled_plugins;
+ is( scalar @enabled_plugins, 2, '2 enabled plugins' );
+
+ reload_plugin( $_, $plugin_mocks ) for 3 .. 4;
+ Koha::Plugins->RemovePlugins( { plugin_class => "${class_basename}4" } );
+ is( Koha::Plugins::Datas->count, 4, '4 in plugin_data' );
+ is( Koha::Plugins::Methods->count, 1, '1 in plugin_methods' );
+ @enabled_plugins = Koha::Plugins->get_enabled_plugins;
+ is( scalar @enabled_plugins, 2, '2 enabled plugins (from cache)' );
+
+ # clear cache and try again, expect 4 since RemovePlugins did not touch plugin_data here
+ Koha::Cache::Memory::Lite->clear_from_cache( Koha::Plugins->ENABLED_PLUGINS_CACHE_KEY );
+ @enabled_plugins = Koha::Plugins->get_enabled_plugins;
+ is( scalar @enabled_plugins, 4, '4 enabled plugins' );
+ Koha::Plugins->RemovePlugins( { destructive => 1 } );
+ };
+
+ $schema->storage->txn_rollback;
+};
+
+
+$schema->storage->txn_begin; # Matching rollback at very end
subtest 'output and output_html tests' => sub {
@@ -412,5 +499,5 @@ subtest 'new() tests' => sub {
is( ref($result), 'Koha::Plugins', 'calling new with enable_plugins makes it override the config' );
};
-Koha::Plugins::Methods->delete;
$schema->storage->txn_rollback;
+#!/usr/bin/perl
--
2.30.2