From 6f97617e32c45e827a7aa3d9ee9e617e9530dda9 Mon Sep 17 00:00:00 2001 From: Marcel de Rooy 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 Signed-off-by: Martin Renvoize Signed-off-by: Kyle M Hall Signed-off-by: Katrin Fischer (cherry picked from commit 950c1e63f864ea1b1a194d685b2d8bd7ae83190d) Signed-off-by: Fridolin Somers --- 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 72ae308f3f..3f2bed2196 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 71497a3036..3037ed801e 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.39.5