From 1261ff452a051affc289a9eef3054ca6e23a0a62 Mon Sep 17 00:00:00 2001 From: Kyle M Hall Date: Thu, 16 Apr 2020 11:50:28 -0400 Subject: [PATCH] Bug 24631: Plugin metadata should be outside the main class Currently, plugin metadata is stored within the main plugin class file but this means one has to load the class to read it. We should pull this data out into a manifest/metadata file in a standard format (JSON/YAML) to allow simpler external parsing. Test Plan: 1) Apply this patch 2) Install the latest Kitchen Sink plugin: https://github.com/bywatersolutions/koha-plugin-kitchen-sink/releases/download/v2.1.39/koha-plugin-kitchen-sink-v2.1.39.kpz 3) Browse to plugins home, note that nothing appears to have changed 4) Browse to your pluginsdir, find the PLUGIN.yml file for the Kitchen Sink plugin, edit some of the metadata 5) Reload the plugins home page, note your changes to PLUGIN.yml appear in the plugins table! Signed-off-by: Victor Grousset/tuxayo --- Koha/Plugins.pm | 75 ++++++++++++++++++- Koha/Plugins/Base.pm | 22 +++++- Koha/Plugins/Data.pm | 54 +++++++++++++ Koha/Plugins/Datum.pm | 44 +++++++++++ .../prog/en/modules/plugins/plugins-home.tt | 28 +++---- plugins/plugins-home.pl | 4 +- 6 files changed, 207 insertions(+), 20 deletions(-) create mode 100644 Koha/Plugins/Data.pm create mode 100644 Koha/Plugins/Datum.pm diff --git a/Koha/Plugins.pm b/Koha/Plugins.pm index 9dc42c5155..b70d00f011 100644 --- a/Koha/Plugins.pm +++ b/Koha/Plugins.pm @@ -21,17 +21,21 @@ use Modern::Perl; use Class::Inspector; use List::MoreUtils qw(any); -use Module::Load::Conditional qw(can_load); use Module::Load qw(load); +use Module::Load::Conditional qw(can_load); use Module::Pluggable search_path => ['Koha::Plugin'], except => qr/::Edifact(|::Line|::Message|::Order|::Segment|::Transport)$/; +use YAML qw(Load Dump); use C4::Context; use C4::Output; use Koha::Plugins::Methods; +use Koha::Plugins::Data; + +our @pluginsdir; BEGIN { my $pluginsdir = C4::Context->config("pluginsdir"); - my @pluginsdir = ref($pluginsdir) eq 'ARRAY' ? @$pluginsdir : $pluginsdir; + @pluginsdir = ref($pluginsdir) eq 'ARRAY' ? @$pluginsdir : $pluginsdir; push( @INC, @pluginsdir ); pop @INC if $INC[-1] eq '.'; } @@ -112,6 +116,63 @@ sub GetPlugins { return @plugins; } +sub GetPluginsMetadata { + my ( $self, $params ) = @_; + + my $method = $params->{method}; + my $req_metadata = $params->{metadata} // {}; + + my $filter = ( $method ) ? { plugin_method => $method } : undef; + + my $plugin_classes = Koha::Plugins::Methods->search( + $filter, + { columns => 'plugin_class', + distinct => 1 + } + )->_resultset->get_column('plugin_class'); + + my @plugins; + while ( my $plugin_class = $plugin_classes->next ) { + my $plugin_metadata = Koha::Plugins::Data->find( + { + plugin_class => $plugin_class, + plugin_key => 'metadata', + } + ); + + if ( $plugin_metadata ) { + $plugin_metadata = YAML::Load( $plugin_metadata->plugin_value ); + } + else { + load $plugin_class; + my $plugin = $plugin_class->new( + { + enable_plugins => $self->{enable_plugins} + } + ); + $plugin_metadata = $plugin->get_metadata; + + Koha::Plugins::Datum->new( + { + plugin_class => $plugin_class, + plugin_key => 'metadata', + plugin_value => YAML::Dump( $plugin_metadata ), + } + ); + } + + next + if $plugin_metadata + and %$req_metadata + and any { !$plugin_metadata->{$_} || $plugin_metadata->{$_} ne $req_metadata->{$_} } keys %$req_metadata; + + push @plugins, $plugin_metadata; + + } + + return @plugins; +} + =head2 InstallPlugins Koha::Plugins::InstallPlugins() @@ -137,6 +198,16 @@ sub InstallPlugins { my $plugin = $plugin_class->new({ enable_plugins => $self->{'enable_plugins'} }); + # Force update plugin metadata in the database + my $metadata = $plugin->get_metadata( { skip_database => 1 } ); + my $params = { + plugin_class => $plugin_class, + plugin_key => 'metadata', + }; + my $db_metadata = Koha::Plugins::Data->find( $params ) || Koha::Plugins::Datum->new( $params ); + $db_metadata->plugin_value( YAML::Dump($metadata) ); + $db_metadata->store(); + Koha::Plugins::Methods->search({ plugin_class => $plugin_class })->delete(); foreach my $method ( @{ Class::Inspector->methods( $plugin_class, 'public' ) } ) { diff --git a/Koha/Plugins/Base.pm b/Koha/Plugins/Base.pm index 6a723c0c15..595dd3cb03 100644 --- a/Koha/Plugins/Base.pm +++ b/Koha/Plugins/Base.pm @@ -19,9 +19,10 @@ package Koha::Plugins::Base; use Modern::Perl; -use Module::Pluggable require => 1; use Cwd qw(abs_path); use List::Util qw(max); +use Module::Pluggable require => 1; +use YAML qw(Load LoadFile); use base qw{Module::Bundled::Files}; @@ -177,8 +178,25 @@ sub get_template { sub get_metadata { my ( $self, $args ) = @_; + my $skip_database = $args->{skip_database}; + + my $metadata = $self->{metadata}; # Check for old style metadata in blessed hash + $metadata ||= $self::metadata; # Check for a global metadata var ( i.e. our $metadata ) + + unless ( $metadata && !$skip_database ) { # Check the database next, unless this is a plugin upgrade + $metadata = $self->retrieve_data('metadata'); + $metadata = YAML::Load( $metadata ); + } + + unless ( $metadata ) { # Check for metadata in PLUGIN.yml, if it exists + my $bundle_path = $self->bundle_path; + my $plugin_yml = "$bundle_path/PLUGIN.yml"; + if ( -r $plugin_yml ) { + $metadata = YAML::LoadFile( $plugin_yml ); + } + } + #FIXME: Why another encoding issue? For metadata containing non latin characters. - my $metadata = $self->{metadata}; $metadata->{$_} && utf8::decode($metadata->{$_}) for keys %$metadata; return $metadata; } diff --git a/Koha/Plugins/Data.pm b/Koha/Plugins/Data.pm new file mode 100644 index 0000000000..a50c9abb80 --- /dev/null +++ b/Koha/Plugins/Data.pm @@ -0,0 +1,54 @@ +package Koha::Plugins::Data; + +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# Koha is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Koha; if not, see . + +use Modern::Perl; + +use Carp; + +use Koha::Database; + +use Koha::Plugins::Datum; + +use base qw(Koha::Objects); + +=head1 NAME + +Koha::Plugin::Data - Koha Plugins Data Object set class + +=head1 API + +=head2 Class Methods + +=cut + +=head3 type + +=cut + +sub _type { + return 'PluginData'; +} + +=head3 object_class + +=cut + +sub object_class { + return 'Koha::Plugins::Datum'; +} + +1; diff --git a/Koha/Plugins/Datum.pm b/Koha/Plugins/Datum.pm new file mode 100644 index 0000000000..1f6f8df0b7 --- /dev/null +++ b/Koha/Plugins/Datum.pm @@ -0,0 +1,44 @@ +package Koha::Plugins::Datum; + +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# Koha is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Koha; if not, see . + +use Modern::Perl; + +use Carp; + +use Koha::Database; + +use base qw(Koha::Object); + +=head1 NAME + +Koha::Plugin::Datum - Koha Plugin Data Object class + +=head1 API + +=head2 Class Methods + +=cut + +=head3 type + +=cut + +sub _type { + return 'PluginData'; +} + +1; diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/plugins/plugins-home.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/plugins/plugins-home.tt index 1b24428fde..edb4c03c46 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/plugins/plugins-home.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/plugins/plugins-home.tt @@ -80,7 +80,7 @@ [% END %] - [% UNLESS ( plugins ) %] + [% UNLESS ( plugins_metadata ) %] [% UNLESS ( method ) %]
No plugins installed
[% ELSE %] @@ -113,10 +113,10 @@ [% END %] - [% FOREACH plugin IN plugins %] + [% FOREACH metadata IN plugins_metadata %] - [% plugin.metadata.name | html %] + [% metadata.name | html %] [% IF ( plugin.is_enabled ) %] ENABLED [% ELSE %] @@ -124,25 +124,25 @@ [% END %] - [% plugin.metadata.description | html %] + [% metadata.description | html %] - [% IF ( plugin.metadata.minimum_version && koha_version < plugin.metadata.minimum_version ) %] + [% IF ( metadata.minimum_version && koha_version < metadata.minimum_version ) %]
Warning: This report was written for a newer version of Koha. Run at your own risk.
[% END %] - [% IF ( plugin.metadata.maximum_version && koha_version > plugin.metadata.maximum_version ) %] + [% IF ( metadata.maximum_version && koha_version > metadata.maximum_version ) %]
Warning: This plugin was written for an older version of Koha. Run at your own risk.
[% END %] - [% plugin.metadata.author | html %] - [% plugin.metadata.version | html %] - [% plugin.metadata.minimum_version | html %] - [% plugin.metadata.maximum_version | html %] - [% plugin.metadata.date_updated | $KohaDates %] + [% metadata.author | html %] + [% metadata.version | html %] + [% metadata.minimum_version | html %] + [% metadata.maximum_version | html %] + [% metadata.date_updated | $KohaDates %] [% IF ( CAN_user_plugins_configure || CAN_user_plugins_manage || CAN_user_plugins_report || CAN_user_plugins_tool ) %]
@@ -168,11 +168,11 @@ [% END %] [% END %] [% IF ( CAN_user_plugins_manage ) %] -
  • Uninstall
  • +
  • Uninstall
  • [% IF ( plugin.is_enabled ) %] -
  • Disable
  • +
  • Disable
  • [% ELSE %] -
  • Enable
  • +
  • Enable
  • [% END %] [% END %] diff --git a/plugins/plugins-home.pl b/plugins/plugins-home.pl index f376e17d08..fc1bba970e 100755 --- a/plugins/plugins-home.pl +++ b/plugins/plugins-home.pl @@ -53,12 +53,12 @@ if ($plugins_enabled) { method => $method, ); - my @plugins = Koha::Plugins->new()->GetPlugins({ + my @plugins = Koha::Plugins->new()->GetPluginsMetadata({ method => $method, all => 1, }); - $template->param( plugins => \@plugins, ); + $template->param( plugins_metadata => \@plugins, ); my @results; if ($plugin_search) { -- 2.24.2 (Apple Git-127)