Bug 20669: Add upgrade method to plugins

It would be nice if plugins had an upgrade method to handle altering tables and such when a new version of a plugin is installed. Right now it must be done in a completely bespoke manner.

Test Plan:
1) Apply this patch
2) Download the 2 most recent releases of the Kitchen Sink plugin
   https://github.com/bywatersolutions/koha-plugin-kitchen-sink/releases
3) Install the earlier release
4) Look at the configuration page, at the bottom it should say the
   plugin has never been upgraded
5) Install the newer release
6) Reload the configuration page, it should now say that the plugin
   was upgraded and give you the date and time of the upgrade

Signed-off-by: Claire Gravely <claire.gravely@bsz-bw.de>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>

Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
This commit is contained in:
Kyle M Hall 2018-04-26 15:07:07 -04:00 committed by Nick Clemens
parent 8577d55d4e
commit 100385196e
3 changed files with 71 additions and 2 deletions

View File

@ -21,6 +21,7 @@ use Modern::Perl;
use Module::Pluggable require => 1;
use Cwd qw(abs_path);
use List::Util qw(max);
use base qw{Module::Bundled::Files};
@ -43,13 +44,26 @@ sub new {
my $self = bless( $args, $class );
my $plugin_version = $self->get_metadata->{version};
my $database_version = $self->retrieve_data('__INSTALLED_VERSION__');
## Run the installation method if it exists and hasn't been run before
if ( $self->can('install') && !$self->retrieve_data('__INSTALLED__') ) {
if ( $self->install() ) {
$self->store_data( { '__INSTALLED__' => 1 } );
if ( my $version = $plugin_version ) {
$self->store_data({ '__INSTALLED_VERSION__' => $version });
}
} else {
warn "Plugin $class failed during installation!";
}
} elsif ( $self->can('upgrade') && $plugin_version && $database_version ) {
if ( _version_compare( $plugin_version, $database_version ) == 1 ) {
if ( $self->upgrade() ) {
$self->store_data({ '__INSTALLED_VERSION__' => $plugin_version });
warn "Plugin $class failed during upgrade!";
}
}
}
return $self;
@ -218,6 +232,43 @@ sub output {
output_with_http_headers( $self->{cgi}, undef, $data, $content_type, $status, $extra_options );
}
=head2 _version_compare
Utility method to compare two version numbers.
Returns 1 if the first argument is the higher version
Returns -1 if the first argument is the lower version
Returns 0 if both versions are equal
if ( _version_compare( '2.6.26', '2.6.0' ) == 1 ) {
print "2.6.26 is greater than 2.6.0\n";
}
=cut
sub _version_compare {
my $ver1 = shift || 0;
my $ver2 = shift || 0;
my @v1 = split /[.+:~-]/, $ver1;
my @v2 = split /[.+:~-]/, $ver2;
for ( my $i = 0 ; $i < max( scalar(@v1), scalar(@v2) ) ; $i++ ) {
# Add missing version parts if one string is shorter than the other
# i.e. 0 should be lt 0.2.1 and not equal, so we append .0
# 0.0.0 <=> 0.2.1 = -1
push( @v1, 0 ) unless defined( $v1[$i] );
push( @v2, 0 ) unless defined( $v2[$i] );
if ( int( $v1[$i] ) > int( $v2[$i] ) ) {
return 1;
}
elsif ( int( $v1[$i] ) < int( $v2[$i] ) ) {
return -1;
}
}
return 0;
}
1;
__END__

View File

@ -2,14 +2,14 @@
use Modern::Perl;
use Test::More tests => 35;
use Archive::Extract;
use CGI;
use File::Basename;
use File::Temp qw( tempdir tempfile );
use FindBin qw($Bin);
use Archive::Extract;
use Module::Load::Conditional qw(can_load);
use Test::MockModule;
use Test::More tests => 37;
use C4::Context;
@ -49,6 +49,7 @@ ok( $plugin->can('opac_head'), 'Test plugin can opac_head' );
ok( $plugin->can('opac_js'), 'Test plugin can opac_js' );
ok( $plugin->can('configure'), 'Test plugin can configure' );
ok( $plugin->can('install'), 'Test plugin can install' );
ok( $plugin->can('upgrade'), 'Test plugin can upgrade' );
ok( $plugin->can('uninstall'), 'Test plugin can install' );
is( Koha::Plugins::Handler->run({ class => "Koha::Plugin::Test", method => 'report', enable_plugins => 1 }), "Koha::Plugin::Test::report", 'Test run plugin report method' );
@ -151,3 +152,15 @@ subtest 'output and output_html tests' => sub {
like($stdout, qr{Content-Type: text/html; charset=UTF-8}, 'Correct content-type');
like($stdout, qr{¡Hola output_html!}, 'Correct data');
};
subtest 'Test _version_compare' => sub {
plan tests => 6;
is( Koha::Plugins::Base::_version_compare( '1.1.1', '2.2.2' ), -1, "1.1.1 is less then 2.2.2" );
is( Koha::Plugins::Base::_version_compare( '2.2.2', '1.1.1' ), 1, "1.1.1 is greater then 2.2.2" );
is( Koha::Plugins::Base::_version_compare( '1.1.1', '1.1.1' ), 0, "1.1.1 is equal to 1.1.1" );
is( Koha::Plugins::Base::_version_compare( '1.01.001', '1.1.1' ), 0, "1.01.001 is equal to 1.1.1" );
is( Koha::Plugins::Base::_version_compare( '1', '1.0.0' ), 0, "1 is equal to 1.0.0" );
is( Koha::Plugins::Base::_version_compare( '1.0', '1.0.0' ), 0, "1.0 is equal to 1.0.0" );
};

View File

@ -80,6 +80,11 @@ sub install {
return "Koha::Plugin::Test::install";
}
sub upgrade {
my ( $self, $args ) = @_;
return "Koha::Plugin::Test::upgrade";
}
sub uninstall {
my ( $self, $args ) = @_;
return "Koha::Plugin::Test::uninstall";