Skip to content

Commit

Permalink
Dancer::Plugin now uses Exporter to export symbols
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexis Sukrieh committed Sep 24, 2010
1 parent 8c3c1d6 commit 0ae185f
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 14 deletions.
3 changes: 3 additions & 0 deletions .perlcriticrc
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ severity = 5

# we use postifx controls
[-ControlStructures::ProhibitPostfixControls]

# we provide syntactic sugar, so we need them
[-Subroutines::ProhibitSubroutinePrototypes]
67 changes: 56 additions & 11 deletions lib/Dancer/Plugin.pm
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package Dancer::Plugin;
use strict;
use warnings;

use base 'Exporter';
use Dancer::Config 'setting';

use base 'Exporter';
Expand All @@ -14,6 +15,8 @@ use vars qw(@EXPORT);
plugin_setting
);

sub register($&);

my @_reserved_keywords = @Dancer::EXPORT;

my $_keywords = {};
Expand All @@ -35,7 +38,7 @@ sub plugin_setting {
return;
}

sub register {
sub register($&) {
my ($keyword, $code) = @_;
my $plugin_name = caller();

Expand All @@ -50,29 +53,31 @@ sub register_plugin {
my ($application) = shift || caller(1);
my ($plugin) = caller();

export_plugin_symbols($plugin => $application);
my @symbols = set_plugin_symbols($plugin);
{
no strict 'refs';
@{"${plugin}::ISA"} = ('Exporter', 'Dancer::Plugin');
@{"${plugin}::EXPORT"} = @symbols;
}
return 1;
}

sub load_plugin {
my ($plugin) = @_;
my $application = caller();

eval "use $plugin";
die "unable to load plugin '$plugin' : $@" if $@;

export_plugin_symbols($plugin => $application);
die "load_plugin is DEPRECATED, you must use 'use' instead";
}

sub export_plugin_symbols {
my ($plugin, $application) = @_;
sub set_plugin_symbols {
my ($plugin) = @_;

for my $keyword (@{$_keywords->{$plugin}}) {
my ($name, $code) = @$keyword;
{
no strict 'refs';
*{"${application}::${name}"} = $code;
*{"${plugin}::${name}"} = $code;
}
}
return map { $_->[0] } @{$_keywords->{$plugin}};
}

1;
Expand Down Expand Up @@ -107,18 +112,47 @@ Create plugins for Dancer
register_plugin;
1;
And in your application:
package My::Webapp;
use Dancer ':syntax';
use Dancer::Plugin::LinkBlocker;
block_links_from; # this is exported by the plugin
=head1 PLUGINS
You can extend Dancer by writing your own Plugin.
A plugin is a module that exports a bunch of symbols to the current namespace
(the caller will see all the symbols defined via C<register>).
Note that you have to C<use> the plugin wherever you want to use its symbols.
For instance, if you have Webapp::App1 and Webapp::App2, both loaded from your
main application, they both need to C<use FooPlugin> if they want to use the
symbols exported by C<FooPlugin>.
=head2 METHODS
=over 4
=item B<register>
Lets you define a keyword that will be exported by the plugin.
register my_symbol_to_export => sub {
# ... some code
};
=item B<register_plugin>
A Dancer plugin must end with this statement. This lets the plugin register all
the symbols define with C<register> as exported symbols (via the L<Exporter>
module).
A Dancer plugin inherits from Dancer::Plugin and Exporter transparently.
=item B<plugin_setting>
Configuration for plugin should be structured like this in the config.yaml of the application:
Expand All @@ -130,3 +164,14 @@ Configuration for plugin should be structured like this in the config.yaml of th
If plugin_setting is called inside a plugin, the appropriate configuration will be returned. The plugin_name should be the name of the package, or, if the plugin name is under the Dancer::Plugin:: namespace, the end part of the plugin name.
=back
=head1 AUTHORS
This module has been written by Alexis Sukrieh and others.
=head1 LICENSE
This module is free software and is published under the same
terms as Perl itself.
=cut
8 changes: 6 additions & 2 deletions t/15_plugins/03_namespace.t
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
# issue #72
# http://github.com/sukria/Dancer/issues#issue/72

use Test::More tests => 2, import => ['!pass'];
use Test::More tests => 3, import => ['!pass'];

use lib 't';
{
use Dancer;

use TestPlugin;
use TestAppExt;

load_plugin 'TestPlugin';
eval { load_plugin 'TestPlugin' };
like $@, qr{load_plugin is DEPRECATED, you must use 'use' instead},
"load_plugin is deprecated";

is(test_plugin_symbol(), "test_plugin_symbol",
"plugin symbol is exported in current namespace");
Expand Down
13 changes: 13 additions & 0 deletions t/15_plugins/04_apps_and_plugins.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use strict;
use warnings;
use Test::More import => ['!pass'];
plan tests => 2;

{
use Dancer ':syntax';
use t::lib::TestPlugin;

load_app 't::lib::Forum';

is(some_plugin_keyword(), 42, 'plugin keyword is exported');
}
2 changes: 1 addition & 1 deletion t/TestAppExt.pm
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use warnings;

use lib 't';
use Dancer ':syntax';
load_plugin 'TestPlugin';
use TestPlugin;

sub test_app_func { test_plugin_symbol() }

Expand Down
1 change: 1 addition & 0 deletions t/lib/Forum.pm
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package t::lib::Forum;

use Dancer ':syntax';
use t::lib::TestPlugin;

get '/' => sub { "root" };
get '/index' => sub { 'forum index' };
Expand Down
14 changes: 14 additions & 0 deletions t/lib/TestPlugin.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package t::lib::TestPlugin;

use strict;
use warnings;

use Dancer ':syntax';
use Dancer::Plugin;

register some_plugin_keyword => sub {
42;
};

register_plugin;
1;

0 comments on commit 0ae185f

Please sign in to comment.