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

(-)a/Koha/Plugins.pm (-14 / +49 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
85
        my $plugin_enabled = $plugin->retrieve_data('__ENABLED__');
86
        $plugin->{enabled} = $plugin_enabled;
87
88
        # Want all plugins. Not only enabled ones.
89
        if ( defined($params->{all}) && $params->{all} ) {
90
            $plugin_enabled = 1;
91
        }
92
93
        next unless $plugin_enabled;
94
95
        push @plugins, $plugin;
96
    }
97
    return @plugins;
98
}
99
100
=head2
101
102
Koha::Plugins::InstallPlugins()
103
104
This method iterates through all plugins physically present on a system.
105
For each plugin module found, it will test that the plugin can be loaded,
106
and if it can, will store its available methods in the plugin_methods table.
107
108
=cut
109
110
sub InstallPlugins {
111
    my ( $self, $params ) = @_;
112
73
    my @plugin_classes = $self->plugins();
113
    my @plugin_classes = $self->plugins();
74
    my @plugins;
114
    my @plugins;
75
115
Lines 79-100 sub GetPlugins { Link Here
79
119
80
            my $plugin = $plugin_class->new({ enable_plugins => $self->{'enable_plugins'} });
120
            my $plugin = $plugin_class->new({ enable_plugins => $self->{'enable_plugins'} });
81
121
82
            my $plugin_enabled = $plugin->retrieve_data('__ENABLED__');
122
            Koha::Plugins::Methods->search({ plugin_class => $plugin_class })->delete();
83
            $plugin->{enabled} = $plugin_enabled;
84
123
85
            # Want all plugins. Not only enabled ones.
124
            foreach my $method ( @{ Class::Inspector->methods($plugin_class) } ) {
86
            if ( defined($params->{all}) && $params->{all} ) {
125
                Koha::Plugins::Method->new(
87
                $plugin_enabled = 1;
126
                    {
127
                        plugin_class  => $plugin_class,
128
                        plugin_method => $method,
129
                    }
130
                )->store();
88
            }
131
            }
89
132
90
            next unless $plugin_enabled;
91
92
            # Limit results by method or metadata
93
            next if $method && !$plugin->can($method);
94
            my $plugin_metadata = $plugin->get_metadata;
95
            next if $plugin_metadata
96
                and %$req_metadata
97
                and any { !$plugin_metadata->{$_} || $plugin_metadata->{$_} ne $req_metadata->{$_} } keys %$req_metadata;
98
            push @plugins, $plugin;
133
            push @plugins, $plugin;
99
        } else {
134
        } else {
100
            my $error = $Module::Load::Conditional::ERROR;
135
            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 => 47; 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 93-104 is( scalar grep( /^Test Plugin$/, @names), 1, "Koha::Plugins::GetPlugins functio Link Here
93
98
94
@names = map { $_->get_metadata()->{'name'} } @plugins;
99
@names = map { $_->get_metadata()->{'name'} } @plugins;
95
is( scalar grep( /^Test Plugin$/, @names), 1, "GetPlugins also found Test Plugin via a metadata tag" );
100
is( scalar grep( /^Test Plugin$/, @names), 1, "GetPlugins also found Test Plugin via a metadata tag" );
96
# Test two metadata conditions; one does not exist for Test.pm
97
# Since it is a required key, we should not find the same results
98
my @plugins2 = Koha::Plugins->new({ enable_plugins => 1 })->GetPlugins({
99
    metadata => { my_example_tag  => 'find_me', not_there => '1' },
100
});
101
isnt( scalar @plugins2, scalar @plugins, 'GetPlugins with two metadata conditions' );
102
101
103
$result = $plugin->disable;
102
$result = $plugin->disable;
104
is( ref($result), 'Koha::Plugin::Test' );
103
is( ref($result), 'Koha::Plugin::Test' );
Lines 141-146 for my $pass ( 1 .. 2 ) { Link Here
141
140
142
    ok( -f $plugins_dir . "/Koha/Plugin/Com/ByWaterSolutions/KitchenSink.pm", "KitchenSink plugin installed successfully" );
141
    ok( -f $plugins_dir . "/Koha/Plugin/Com/ByWaterSolutions/KitchenSink.pm", "KitchenSink plugin installed successfully" );
143
    $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"
142
    $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"
143
    Koha::Plugins->new( { enable_plugins => 1 } )->InstallPlugins();
144
    Koha::Plugins::Handler->delete({ class => "Koha::Plugin::Com::ByWaterSolutions::KitchenSink", enable_plugins => 1 });
144
    Koha::Plugins::Handler->delete({ class => "Koha::Plugin::Com::ByWaterSolutions::KitchenSink", enable_plugins => 1 });
145
    my $sth = C4::Context->dbh->table_info( undef, undef, $table, 'TABLE' );
145
    my $sth = C4::Context->dbh->table_info( undef, undef, $table, 'TABLE' );
146
    my $info = $sth->fetchall_arrayref;
146
    my $info = $sth->fetchall_arrayref;
147
- 

Return to bug 21073