View | Details | Raw Unified | Return to bug 21073
Collapse All | Expand All

(-)a/Koha/Plugins.pm (-7 / +41 lines)
Lines 19-30 package Koha::Plugins; Link Here
19
19
20
use Modern::Perl;
20
use Modern::Perl;
21
21
22
use Class::Inspector;
23
use List::MoreUtils qw( any );
22
use Module::Load::Conditional qw(can_load);
24
use Module::Load::Conditional qw(can_load);
25
use Module::Load qw(load);
23
use Module::Pluggable search_path => ['Koha::Plugin'], except => qr/::Edifact(|::Line|::Message|::Order|::Segment|::Transport)$/;
26
use Module::Pluggable search_path => ['Koha::Plugin'], except => qr/::Edifact(|::Line|::Message|::Order|::Segment|::Transport)$/;
24
use List::MoreUtils qw( any );
25
27
26
use C4::Context;
28
use C4::Context;
27
use C4::Output;
29
use C4::Output;
30
use Koha::Plugins::Methods;
28
31
29
BEGIN {
32
BEGIN {
30
    my $pluginsdir = C4::Context->config("pluginsdir");
33
    my $pluginsdir = C4::Context->config("pluginsdir");
Lines 70-75 sub GetPlugins { Link Here
70
    my $method = $params->{method};
73
    my $method = $params->{method};
71
    my $req_metadata = $params->{metadata} // {};
74
    my $req_metadata = $params->{metadata} // {};
72
75
76
    my $dbh = C4::Context->dbh;
77
    my $plugin_classes = $dbh->selectcol_arrayref('SELECT DISTINCT(plugin_class) FROM plugin_methods');
78
    my @plugins;
79
80
    foreach my $plugin_class (@$plugin_classes) {
81
        next if $method && !Koha::Plugins::Methods->search({ plugin_class => $plugin_class, plugin_method => $method })->count;
82
        load $plugin_class;
83
        my $plugin = $plugin_class->new({ enable_plugins => $self->{'enable_plugins'} });
84
        push @plugins, $plugin;
85
    }
86
    return @plugins;
87
}
88
89
=head2
90
91
Koha::Plugins::InstallPlugins()
92
93
This method iterates through all plugins physically present on a system.
94
For each plugin module found, it will test that the plugin can be loaded,
95
and if it can, will store its available methods in the plugin_methods table.
96
97
=cut
98
99
sub InstallPlugins {
100
    my ( $self, $params ) = @_;
101
73
    my @plugin_classes = $self->plugins();
102
    my @plugin_classes = $self->plugins();
74
    my @plugins;
103
    my @plugins;
75
104
Lines 79-90 sub GetPlugins { Link Here
79
108
80
            my $plugin = $plugin_class->new({ enable_plugins => $self->{'enable_plugins'} });
109
            my $plugin = $plugin_class->new({ enable_plugins => $self->{'enable_plugins'} });
81
110
82
            # Limit results by method or metadata
111
            Koha::Plugins::Methods->search({ plugin_class => $plugin_class })->delete();
83
            next if $method && !$plugin->can($method);
112
84
            my $plugin_metadata = $plugin->get_metadata;
113
            foreach my $method ( @{ Class::Inspector->methods($plugin_class) } ) {
85
            next if $plugin_metadata
114
                Koha::Plugins::Method->new(
86
                and %$req_metadata
115
                    {
87
                and any { !$plugin_metadata->{$_} || $plugin_metadata->{$_} ne $req_metadata->{$_} } keys %$req_metadata;
116
                        plugin_class  => $plugin_class,
117
                        plugin_method => $method,
118
                    }
119
                )->store();
120
            }
121
88
            push @plugins, $plugin;
122
            push @plugins, $plugin;
89
        } else {
123
        } else {
90
            my $error = $Module::Load::Conditional::ERROR;
124
            my $error = $Module::Load::Conditional::ERROR;
(-)a/Koha/Plugins/Handler.pm (-8 / +10 lines)
Lines 21-29 use Modern::Perl; Link Here
21
21
22
use File::Path qw(remove_tree);
22
use File::Path qw(remove_tree);
23
23
24
use Module::Load::Conditional qw(can_load);
24
use Module::Load qw(load);
25
25
26
use C4::Context;
26
use C4::Context;
27
use Koha::Plugins::Methods;
27
28
28
BEGIN {
29
BEGIN {
29
    my $pluginsdir = C4::Context->config("pluginsdir");
30
    my $pluginsdir = C4::Context->config("pluginsdir");
Lines 61-75 sub run { Link Here
61
    my $cgi           = $args->{'cgi'};
62
    my $cgi           = $args->{'cgi'};
62
    my $params        = $args->{'params'};
63
    my $params        = $args->{'params'};
63
64
64
    if ( can_load( modules => { $plugin_class => undef } ) ) {
65
    my $has_method = Koha::Plugins::Methods->search({ plugin_class => $plugin_class, plugin_method => $plugin_method })->count();
66
    if ( $has_method ) {
67
        load $plugin_class;
65
        my $plugin = $plugin_class->new( { cgi => $cgi, enable_plugins => $args->{'enable_plugins'} } );
68
        my $plugin = $plugin_class->new( { cgi => $cgi, enable_plugins => $args->{'enable_plugins'} } );
66
        if ( $plugin->can($plugin_method) ) {
69
        my @return = $plugin->$plugin_method( $params );
67
            return $plugin->$plugin_method( $params );
70
        return $plugin->$plugin_method( $params );
68
        } else {
69
            warn "Plugin does not have method $plugin_method";
70
        }
71
    } else {
71
    } else {
72
        warn "Plugin $plugin_class cannot be loaded";
72
        warn "Plugin does not have method $plugin_method";
73
        return undef;
73
    }
74
    }
74
}
75
}
75
76
Lines 101-106 sub delete { Link Here
101
    });
102
    });
102
103
103
    C4::Context->dbh->do( "DELETE FROM plugin_data WHERE plugin_class = ?", undef, ($plugin_class) );
104
    C4::Context->dbh->do( "DELETE FROM plugin_data WHERE plugin_class = ?", undef, ($plugin_class) );
105
    Koha::Plugins::Methods->search({ plugin_class => $plugin_class })->delete();
104
106
105
    unlink "$plugin_path.pm" or warn "Could not unlink $plugin_path.pm: $!";
107
    unlink "$plugin_path.pm" or warn "Could not unlink $plugin_path.pm: $!";
106
    remove_tree($plugin_path);
108
    remove_tree($plugin_path);
(-)a/Koha/Plugins/Methods.pm (-1 / +1 lines)
Lines 21-27 use Carp; Link Here
21
21
22
use Koha::Database;
22
use Koha::Database;
23
23
24
use Koha::City;
24
use Koha::Plugins::Method;
25
25
26
use base qw(Koha::Objects);
26
use base qw(Koha::Objects);
27
27
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt (-2 lines)
Lines 98-110 Link Here
98
                </dl>
98
                </dl>
99
            [% END %]
99
            [% END %]
100
100
101
            [% IF CAN_user_plugins && plugins_enabled %]
102
                <h3>Plugins</h3>
101
                <h3>Plugins</h3>
103
                <dl>
102
                <dl>
104
                    <dt><a href="/cgi-bin/koha/plugins/plugins-home.pl">Manage plugins</a></dt>
103
                    <dt><a href="/cgi-bin/koha/plugins/plugins-home.pl">Manage plugins</a></dt>
105
                    <dd>View, manage, configure and run plugins.</dd>
104
                    <dd>View, manage, configure and run plugins.</dd>
106
                </dl>
105
                </dl>
107
            [% END %]
108
            </div>
106
            </div>
109
107
110
            <div class="col-md-6 sysprefs">
108
            <div class="col-md-6 sysprefs">
(-)a/plugins/plugins-upload.pl (-2 / +5 lines)
Lines 19-27 Link Here
19
use Modern::Perl;
19
use Modern::Perl;
20
20
21
use Archive::Extract;
21
use Archive::Extract;
22
use File::Temp;
23
use File::Copy;
24
use CGI qw ( -utf8 );
22
use CGI qw ( -utf8 );
23
use Class::Inspector;
24
use File::Copy;
25
use File::Temp;
25
26
26
use C4::Context;
27
use C4::Context;
27
use C4::Auth;
28
use C4::Auth;
Lines 86-91 if ($plugins_enabled) { Link Here
86
                $template->param( ERRORS => [ \%errors ] );
87
                $template->param( ERRORS => [ \%errors ] );
87
                output_html_with_http_headers $input, $cookie, $template->output;
88
                output_html_with_http_headers $input, $cookie, $template->output;
88
                exit;
89
                exit;
90
            } else {
91
                Koha::Plugins->new()->InstallPlugins();
89
            }
92
            }
90
        }
93
        }
91
    } elsif ( ( $op eq 'Upload' ) && !$uploadfile ) {
94
    } elsif ( ( $op eq 'Upload' ) && !$uploadfile ) {
(-)a/t/db_dependent/Plugins.t (-7 / +6 lines)
Lines 13-18 use Test::More tests => 42; Link Here
13
13
14
use C4::Context;
14
use C4::Context;
15
use Koha::Database;
15
use Koha::Database;
16
use Koha::Plugins::Methods;
16
17
17
use t::lib::Mocks;
18
use t::lib::Mocks;
18
19
Lines 27-32 BEGIN { Link Here
27
28
28
my $schema = Koha::Database->new->schema;
29
my $schema = Koha::Database->new->schema;
29
30
31
Koha::Plugins->new( { enable_plugins => 1 } )->InstallPlugins();
32
33
ok( Koha::Plugins::Methods->search( { plugin_class => 'Koha::Plugin::Test' } )->count, 'Test plugin methods added to database' );
34
30
my $mock_plugin = Test::MockModule->new( 'Koha::Plugin::Test' );
35
my $mock_plugin = Test::MockModule->new( 'Koha::Plugin::Test' );
31
$mock_plugin->mock( 'test_template', sub {
36
$mock_plugin->mock( 'test_template', sub {
32
    my ( $self, $file ) = @_;
37
    my ( $self, $file ) = @_;
Lines 88-99 is( scalar grep( /^Test Plugin$/, @names), 1, "Koha::Plugins::GetPlugins functio Link Here
88
});
93
});
89
@names = map { $_->get_metadata()->{'name'} } @plugins;
94
@names = map { $_->get_metadata()->{'name'} } @plugins;
90
is( scalar grep( /^Test Plugin$/, @names), 1, "GetPlugins also found Test Plugin via a metadata tag" );
95
is( scalar grep( /^Test Plugin$/, @names), 1, "GetPlugins also found Test Plugin via a metadata tag" );
91
# Test two metadata conditions; one does not exist for Test.pm
92
# Since it is a required key, we should not find the same results
93
my @plugins2 = Koha::Plugins->new({ enable_plugins => 1 })->GetPlugins({
94
    metadata => { my_example_tag  => 'find_me', not_there => '1' },
95
});
96
isnt( scalar @plugins2, scalar @plugins, 'GetPlugins with two metadata conditions' );
97
96
98
for my $pass ( 1 .. 2 ) {
97
for my $pass ( 1 .. 2 ) {
99
    my $plugins_dir;
98
    my $plugins_dir;
Lines 125-130 for my $pass ( 1 .. 2 ) { Link Here
125
124
126
    ok( -f $plugins_dir . "/Koha/Plugin/Com/ByWaterSolutions/KitchenSink.pm", "KitchenSink plugin installed successfully" );
125
    ok( -f $plugins_dir . "/Koha/Plugin/Com/ByWaterSolutions/KitchenSink.pm", "KitchenSink plugin installed successfully" );
127
    $INC{$pm_path} = $full_pm_path; # FIXME I do not really know why, but if this is moved before the $plugin constructor, it will fail with Can't locate object method "new" via package "Koha::Plugin::Com::ByWaterSolutions::KitchenSink"
126
    $INC{$pm_path} = $full_pm_path; # FIXME I do not really know why, but if this is moved before the $plugin constructor, it will fail with Can't locate object method "new" via package "Koha::Plugin::Com::ByWaterSolutions::KitchenSink"
127
    Koha::Plugins->new( { enable_plugins => 1 } )->InstallPlugins();
128
    Koha::Plugins::Handler->delete({ class => "Koha::Plugin::Com::ByWaterSolutions::KitchenSink", enable_plugins => 1 });
128
    Koha::Plugins::Handler->delete({ class => "Koha::Plugin::Com::ByWaterSolutions::KitchenSink", enable_plugins => 1 });
129
    my $sth = C4::Context->dbh->table_info( undef, undef, $table, 'TABLE' );
129
    my $sth = C4::Context->dbh->table_info( undef, undef, $table, 'TABLE' );
130
    my $info = $sth->fetchall_arrayref;
130
    my $info = $sth->fetchall_arrayref;
131
- 

Return to bug 21073