Bugzilla – Attachment 104256 Details for
Bug 24631
Plugin metadata should be outside the main class
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 24631: Plugin metadata should be outside the main class
Bug-24631-Plugin-metadata-should-be-outside-the-ma.patch (text/plain), 20.74 KB, created by
Kyle M Hall (khall)
on 2020-05-04 11:21:56 UTC
(
hide
)
Description:
Bug 24631: Plugin metadata should be outside the main class
Filename:
MIME Type:
Creator:
Kyle M Hall (khall)
Created:
2020-05-04 11:21:56 UTC
Size:
20.74 KB
patch
obsolete
>From cb429c92383a1651bdb214130164c730082e6b2d Mon Sep 17 00:00:00 2001 >From: Kyle M Hall <kyle@bywatersolutions.com> >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 > Restart Plack > 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 > Restart Plack > 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 > Restart Plack >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 > Restart Plack >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! >20) Test that you can enable/disable the plugin >21) Test that all the plugin methods ( configure, report, tool ) still work >22) Test that you can uninstall the plugin >--- > Koha/Plugins.pm | 94 ++++++++++++++++++- > Koha/Plugins/Base.pm | 27 +++++- > 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, 240 insertions(+), 31 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..ca28968d8e 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} = { map { $_->plugin_method => 1 } @plugin_methods }; >+ >+ 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..618cded530 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}; > >@@ -58,7 +59,7 @@ sub new { > warn "Plugin $class failed during installation!"; > } > } elsif ( $self->can('upgrade') ) { >- if ( _version_compare( $plugin_version, $database_version ) == 1 ) { >+ if ( $self->_version_compare( $plugin_version, $database_version ) == 1 ) { > if ( $self->upgrade() ) { > $self->store_data({ '__INSTALLED_VERSION__' => $plugin_version }); > } else { >@@ -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 <http://www.gnu.org/licenses>. >+ >+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 <http://www.gnu.org/licenses>. >+ >+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 @@ > </table> > [% END %] > >- [% UNLESS ( plugins ) %] >+ [% UNLESS ( plugins_metadata ) %] > [% UNLESS ( method ) %] > <div class="dialog message">No plugins installed</div> > [% ELSE %] >@@ -113,66 +113,66 @@ > [% END %] > </tr> > >- [% FOREACH plugin IN plugins %] >+ [% FOREACH metadata IN plugins_metadata %] > <tr> > <td> >- <strong>[% plugin.metadata.name | html %]</strong> >- [% IF ( plugin.is_enabled ) %] >+ <strong>[% metadata.name | html %]</strong> >+ [% IF ( metadata.is_enabled ) %] > <span class="label label-primary">ENABLED</span> > [% ELSE %] > <span class="label label-default">DISABLED</span> > [% END %] > </td> > <td> >- [% 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 ) %] > <div class="dialog alert"> > Warning: This report was written for a newer version of Koha. Run at your own risk. > </div> > [% END %] > >- [% IF ( plugin.metadata.maximum_version && koha_version > plugin.metadata.maximum_version ) %] >+ [% IF ( metadata.maximum_version && koha_version > metadata.maximum_version ) %] > <div class="dialog alert"> > Warning: This plugin was written for an older version of Koha. Run at your own risk. > </div> > [% END %] > </td> >- <td>[% plugin.metadata.author | html %]</td> >- <td>[% plugin.metadata.version | html %]</td> >- <td>[% plugin.metadata.minimum_version | html %]</td> >- <td>[% plugin.metadata.maximum_version | html %]</td> >- <td>[% plugin.metadata.date_updated | $KohaDates %]</td> >+ <td>[% metadata.author | html %]</td> >+ <td>[% metadata.version | html %]</td> >+ <td>[% metadata.minimum_version | html %]</td> >+ <td>[% metadata.maximum_version | html %]</td> >+ <td>[% metadata.date_updated | $KohaDates %]</td> > [% IF ( CAN_user_plugins_configure || CAN_user_plugins_manage || CAN_user_plugins_report || CAN_user_plugins_tool ) %] > <td class="actions"> > <div class="btn-group dropup"> >- <a class="btn btn-default btn-xs dropdown-toggle" id="pluginactions[% plugin.class | html %]" role="button" data-toggle="dropdown" href="#"> >+ <a class="btn btn-default btn-xs dropdown-toggle" id="pluginactions[% metadata.class | html %]" role="button" data-toggle="dropdown" href="#"> > Actions <b class="caret"></b> > </a> >- <ul class="dropdown-menu pull-right" role="menu" aria-labelledby="pluginactions[% plugin.class | html %]"> >+ <ul class="dropdown-menu pull-right" role="menu" aria-labelledby="pluginactions[% metadata.class | html %]"> > [% IF ( CAN_user_plugins_report ) %] >- [% IF plugin.can('report') %] >- <li><a href="/cgi-bin/koha/plugins/run.pl?class=[% plugin.class | uri %]&method=report"><i class="fa fa-table fa-fw"></i> Run report</a></li> >+ [% IF metadata.can.report %] >+ <li><a href="/cgi-bin/koha/plugins/run.pl?class=[% metadata.class | uri %]&method=report"><i class="fa fa-table fa-fw"></i> Run report</a></li> > [% END %] > [% END %] > > [% IF ( CAN_user_plugins_tool ) %] >- [% IF plugin.can('tool') %] >- <li><a href="/cgi-bin/koha/plugins/run.pl?class=[% plugin.class | uri %]&method=tool"><i class="fa fa-wrench fa-fw"></i> Run tool</a></li> >+ [% IF metadata.can.tool %] >+ <li><a href="/cgi-bin/koha/plugins/run.pl?class=[% metadata.class | uri %]&method=tool"><i class="fa fa-wrench fa-fw"></i> Run tool</a></li> > [% END %] > [% END %] > > [% IF ( CAN_user_plugins_configure ) %] >- [% IF plugin.can('configure') %] >- <li><a href="/cgi-bin/koha/plugins/run.pl?class=[% plugin.class | uri %]&method=configure"><i class="fa fa-cog fa-fw"></i> Configure</a></li> >+ [% IF metadata.can.configure %] >+ <li><a href="/cgi-bin/koha/plugins/run.pl?class=[% metadata.class | uri %]&method=configure"><i class="fa fa-cog fa-fw"></i> Configure</a></li> > [% END %] > [% END %] > [% IF ( CAN_user_plugins_manage ) %] >- <li><a class="uninstall_plugin" data-plugin-name="[% plugin.metadata.name | html %]" href="/cgi-bin/koha/plugins/plugins-uninstall.pl?class=[% plugin.class | html %]"><i class="fa fa-trash fa-fw"></i> Uninstall</a></li> >- [% IF ( plugin.is_enabled ) %] >- <li><a class="enable_plugin" data-plugin-name="[% plugin.metadata.name | html %]" href="/cgi-bin/koha/plugins/plugins-enable.pl?class=[% plugin.class | html %]&method=disable"><i class="fa fa-pause fa-fw"></i> Disable</a></li> >+ <li><a class="uninstall_plugin" data-plugin-name="[% metadata.name | html %]" href="/cgi-bin/koha/plugins/plugins-uninstall.pl?class=[% metadata.class | html %]"><i class="fa fa-trash fa-fw"></i> Uninstall</a></li> >+ [% IF ( metadata.is_enabled ) %] >+ <li><a class="enable_plugin" data-plugin-name="[% metadata.name | html %]" href="/cgi-bin/koha/plugins/plugins-enable.pl?class=[% metadata.class | html %]&method=disable"><i class="fa fa-pause fa-fw"></i> Disable</a></li> > [% ELSE %] >- <li><a class="enable_plugin" data-plugin-name="[% plugin.metadata.name | html %]" href="/cgi-bin/koha/plugins/plugins-enable.pl?class=[% plugin.class | html %]&method=enable"><i class="fa fa-play fa-fw"></i> Enable</a></li> >+ <li><a class="enable_plugin" data-plugin-name="[% metadata.name | html %]" href="/cgi-bin/koha/plugins/plugins-enable.pl?class=[% metadata.class | html %]&method=enable"><i class="fa fa-play fa-fw"></i> Enable</a></li> > [% END %] > [% END %] > </ul> >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)
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 24631
:
103092
|
103467
|
103468
|
103656
|
103722
|
103982
|
103983
|
104023
|
104024
|
104256
|
104266
|
104270