From 6bbba1c67536581c45b4f72d37db07f8096cbc61 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) Look in plugin_data for the new "__METADATA__" key, note it has the metadata in it 4) Alter the metadata in KitchenSink.pm, delete __METADATA__ from plugin_data 5) Browse to plugins home, note that nothing appears to have changed 6) Note the metadata in plugin_data has been regenerated 7) Browse to your pluginsdir, find the KitchenSink.pm file for the Kitchen Sink plugin, edit some of the metadata 8) Delete the plugin_data metadata again 9) Reload the plugins home 10) Note the metdata has been updated 11) Remove lines 28-40, 47-49 from KitchenSink.pm, this will cause Koha to look at PLUGIN.yml instead 12) Clear the metadata from plugin_data again 13) Reload the plugins home 14) Note again the metadata is regenerated in plugin_data 15) Browse to your pluginsdir, find the PLUGIN.yml file for the Kitchen Sink plugin, edit some of the metadata 16) Clear the metadata from plugin_data again 17) Reload the plugins home 18) Note again the metadata is regenerated in plugin_data 19) 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 | 94 ++++++++++++++++++- Koha/Plugins/Base.pm | 25 ++++- Koha/Plugins/Data.pm | 54 +++++++++++ Koha/Plugins/Datum.pm | 44 +++++++++ .../prog/en/modules/plugins/plugins-home.tt | 48 +++++----- plugins/plugins-home.pl | 4 +- 6 files changed, 239 insertions(+), 30 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..12f59989d8 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,82 @@ 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 ), + } + )->store(); + } + + my $plugin_enabled = Koha::Plugins::Data->find( + { + plugin_class => $plugin_class, + plugin_key => '__ENABLED__', + } + ); + $plugin_metadata->{is_enabled} = $plugin_enabled->plugin_value; + + my @plugin_methods = Koha::Plugins::Methods->search( + { + plugin_class => $plugin_class, + }, + { + columns => 'plugin_method', + } + ); + $plugin_metadata->{can}->{ $_->plugin_method } = 1 foreach @plugin_methods; + warn Data::Dumper::Dumper( $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 +217,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..a252b2aac7 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,28 @@ 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 ); + } + } + + my $class = ref($self); + $metadata->{class} = $class; + #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..245b26a607 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,66 +113,66 @@ [% END %] - [% FOREACH plugin IN plugins %] + [% FOREACH metadata IN plugins_metadata %] - [% plugin.metadata.name | html %] - [% IF ( plugin.is_enabled ) %] + [% metadata.name | html %] + [% IF ( metadata.is_enabled ) %] ENABLED [% ELSE %] DISABLED [% 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 ) %]
- + Actions -