From 009bc3e3c83f61df74590e43ea51ca8331ba33d9 Mon Sep 17 00:00:00 2001 From: Jacob O'Mara Date: Wed, 2 Apr 2025 10:28:15 +0100 Subject: [PATCH] Bug 39522: Allow Valuebuilders to be installable as plugins --- Koha/FrameworkPlugin.pm | 41 ++++++++++++++++++++++++++++++- Koha/Plugins.pm | 36 +++++++++++++++++++++++++++ Koha/Plugins/Base.pm | 36 +++++++++++++++++++++++++++ admin/marc_subfields_structure.pl | 25 +++++++++++++++++++ 4 files changed, 137 insertions(+), 1 deletion(-) mode change 100755 => 100644 admin/marc_subfields_structure.pl diff --git a/Koha/FrameworkPlugin.pm b/Koha/FrameworkPlugin.pm index ba1521211a..4427f97d21 100644 --- a/Koha/FrameworkPlugin.pm +++ b/Koha/FrameworkPlugin.pm @@ -213,6 +213,37 @@ sub _error { sub _load { my ($self) = @_; + # Try to find the class that can handle this plugin + my @plugins = Koha::Plugins->new()->get_valuebuilders_installed(); + + foreach my $vb (@plugins) { + my $plugin = $vb->{plugin}; + + # Check if this plugin provides the value builder we need + if ( $vb->{name} eq $self->{name} ) { + + # Store the plugin object for later use + $self->{plugin} = $plugin; + + # Get the builder and launcher directly from the plugin object + if ( $plugin->can('builder_code') ) { + $self->{builder} = sub { return $plugin->builder_code(@_); }; + } + + if ( $plugin->can('launcher') ) { + $self->{launcher} = sub { return $plugin->launcher(@_); }; + } + + if ( !$self->{builder} && !$self->{launcher} ) { + return $self->_error('Plugin does not contain builder_code nor launcher methods'); + } + + $self->{_loaded} = 1; + return 1; + } + } + + # If not found via plugin, try in standard dir my ( $rv, $file ); return $self->_error('Plugin needs a name') if !$self->{name}; #2chk $self->{path} //= _valuebuilderpath(); @@ -291,12 +322,20 @@ sub _generate_js { return $self->_error('Builder sub not defined'); } + # Make a copy of params and add the plugin object to it + my $builder_params = {%$params}; + + # Add the value builder's plugin if available + if ( $self->{name} && $self->{plugin} ) { + $builder_params->{plugin} = $self->{plugin}; + } + my @params = $self->{oldschool} // 0 ? ( $params->{dbh}, $params->{record}, $params->{tagslib}, $params->{id} ) - : ($params); + : ($builder_params); my @rv = &$sub(@params); return $self->_error( 'Builder sub failed: ' . $@ ) if $@; diff --git a/Koha/Plugins.pm b/Koha/Plugins.pm index 598c815279..71650c66a0 100644 --- a/Koha/Plugins.pm +++ b/Koha/Plugins.pm @@ -378,6 +378,42 @@ sub _restart_after_change { kill 'HUP', $parent_pid; } +=head2 get_valuebuilders_installed + + my @valuebuilders = Koha::Plugins->new->get_valuebuilders_installed(); + +Returns a list of all valuebuilder plugins provided by plugins. + +=cut + +sub get_valuebuilders_installed { + my ($self) = @_; + + # Get ENABLED plugins + my @plugins = $self->get_enabled_plugins(); + + my @valuebuilders; + + foreach my $plugin (@plugins) { + + # Check if plugin implements get_valuebuilder method + if ( $plugin->can('get_valuebuilder') ) { + + # Get the value builder from the plugin + my $valuebuilder = $plugin->get_valuebuilder(); + + if ($valuebuilder) { + push @valuebuilders, { + name => $valuebuilder, + plugin => $plugin, + }; + } + } + } + + return @valuebuilders; +} + 1; __END__ diff --git a/Koha/Plugins/Base.pm b/Koha/Plugins/Base.pm index 75c628e53d..08551b3e53 100644 --- a/Koha/Plugins/Base.pm +++ b/Koha/Plugins/Base.pm @@ -200,6 +200,26 @@ sub get_metadata { return $metadata; } +=head2 get_valuebuilders + + Get valuebuilder identifier provided by this plugin + my $valuebuilder_id = $plugin->get_valuebuilders(); + +=cut + +sub get_valuebuilders { + my ($self) = @_; + + # If this plugin has a get_valuebuilder method that returns a non-empty value, + # return that value in an array reference + if ( $self->can('get_valuebuilder') ) { + my $vb = $self->get_valuebuilder(); + return $vb ? [$vb] : []; + } + + return []; +} + =head2 get_qualified_table_name To avoid naming conflict, each plugins tables should use a fully qualified namespace. @@ -391,6 +411,22 @@ sub disable { return $self; } +=head2 get_valuebuilder_url + + Returns the full URL to launch this plugin's value builder + + my $url = $plugin->get_valuebuilder_url(); + +=cut + +sub get_valuebuilder_url { + my ($self) = @_; + + # Generate the URL to run.pl with the launcher method + my $plugin_class = ref($self); + return "/cgi-bin/koha/plugins/run.pl?class=$plugin_class&method=launcher"; +} + 1; __END__ diff --git a/admin/marc_subfields_structure.pl b/admin/marc_subfields_structure.pl old mode 100755 new mode 100644 index d150ea5c00..72ee9bd151 --- a/admin/marc_subfields_structure.pl +++ b/admin/marc_subfields_structure.pl @@ -126,6 +126,31 @@ if ( $op eq 'add_form' ) { @value_builder = sort { $a cmp $b } @value_builder; closedir $dir_h; + # Add valuebuilders from plugins + if ( C4::Context->config("enable_plugins") ) { + require Koha::Plugins; + my $plugins = Koha::Plugins->new(); + + # Get all plugins first to debug + my @all_plugins = $plugins->GetPlugins(); + foreach my $plugin (@all_plugins) { + ( $plugin->can('get_valuebuilders') ? "yes" : "no" ); + } + + # Use the dedicated get_valuebuilders_installed method + my @plugin_valuebuilders = $plugins->get_valuebuilders_installed(); + + foreach my $vb_entry (@plugin_valuebuilders) { + my $vb_name = $vb_entry->{name}; + + # Avoid duplicates + push( @value_builder, $vb_name ) unless grep { $_ eq $vb_name } @value_builder; + } + + # Re-sort the list after adding plugin valuebuilders + @value_builder = sort { $a cmp $b } @value_builder; + } + # build values list my $mss = Koha::MarcSubfieldStructures->search( { tagfield => $tagfield, frameworkcode => $frameworkcode }, -- 2.39.5