# -*- perl -*- =head1 NAME SuikaWiki::Plugin --- SuikaWiki: Plugin manager and the interface to the Wiki database from plugins =cut package SuikaWiki::Plugin; use strict; our $VERSION = do{my @r=(q$Revision: 1.7 $=~/\d+/g);sprintf "%d."."%02d" x $#r,@r}; our ($plugin_directory, @plugin_directory, %List, %Index, %Cache, %On); push @main::INC, $plugin_directory.'/../..'; require SuikaWiki::Markup::XML; ## Used by plugins =head1 PLUGIN INTERFACE =over 4 =item $o->new_index ($index_name) Increments the index number and returns the new index number. =cut sub new_index ($$) { ++$Index{$_[1]} } =item $o->magic_and_content ($document) (DEPRECATED) Splits the documents into the magic line and content part. Use SuikaWiki::SrcFormat. =cut sub magic_and_content ($$) { my ($magic, $page) = ('', $_[1]); $magic = $1 if $page =~ s!^((?:\#\?|/\*|<\?)[^\x02\x0A\x0D]+)[\x02\x0A\x0D]+!!s; ($magic, $page); } =item $o->feature ($package_name) Returns whether the feature is enabled or not. If the feature is usable but not loaded, it is loaded and C<1> is returned. =cut sub feature ($$;%) { my ($o, $package, %o) = @_; no strict 'refs'; if (${$package . '::VERSION'}) { caller (1)->import if $o{use}; return 1; } else { if (eval qq{require $package}) { caller (1)->import if $o{use}; return 1; } else { return 0; } } } {my %Formatter; sub formatter ($$) { my $t = $_[1]; $t =~ tr/-/_/; unless ($Formatter{$t}) { require Message::Util::Formatter; $Formatter{$t} = Message::Util::Formatter->new; ## SuikaWiki 2 Interface for (@{$SuikaWiki::Plugin::List{'wiki'.$t}||[]}) { $_->load_formatter ($Formatter{$t}, type => 'wiki'.$t); } ## SuikaWiki 2.9 Interface for (keys %{$SuikaWiki::Plugin::Rule{$t}||{}}) { $Formatter{$t}->{$_} = $SuikaWiki::Plugin::Rule{$t}->{$_}->{Formatting}; } $Formatter{$t}->option (return_class => 'SuikaWiki::Markup::XML'); } return $Formatter{$t}; }} sub db ($) { ## TODO: common interface to WikiDB $main::WIKI->{db}; } sub set_data ($$$$;%) { my ($self, $prop, $key, $data, %opt) = @_; ## TODO: common interface to WikiDB ## TODO: error recovering $main::WIKI->{db}->set ($prop => $key => $data); if ($opt{-touch}) { $main::WIKI->{db}->set (lastmodified => $key => time); } } sub get_data ($$$$;%) { my ($self, $prop, $key, %opt) = @_; ## TODO: common interface to WikiDB ## TODO: error recovering $main::WIKI->{db}->get ($prop => $key); } =head1 PLUGIN MANAGER =over 4 =item SuikaWiki::Plugin->import_plugins Searchs plugins into $plugin_directory and loads all plugins found. This method should be called at least one time before plugin-required-features are used. =cut sub import_plugins ($) { my @plugins; for my $dir ($plugin_directory, @plugin_directory) { opendir PDIR, $dir; push @plugins, map {[$_, $dir.'/'.$_.'.pm']} grep {s/\.pm$//} readdir (PDIR); closedir PDIR; } for my $plugin (@plugins) { unless ($plugin->[0] =~ /[^A-Za-z0-9_]/) { eval qq{ require \$plugin->[1]; SuikaWiki::Plugin::$plugin->[0]\->import; 1 } or die $@; push @{$List{_all}}, qq(SuikaWiki::Plugin::$plugin->[0]); } } ## callback (onLoad) for (@{$On{Load}||[]}) { &{$_}; } } =item SuikaWiki::Plugin::regist ($plugin_package, @categories) Regists the plugin categories provided by the plugin package. This method should be called from plugin packages. Example: sub import { my $self = shift; $self->SuikaWiki::Plugin::regist (qw/wikiform_input/); } =cut sub regist ($@) { my $pack = shift; for (@_) { push @{$List{$_}}, $pack; } } =back =head1 WIKIPLUGIN MANAGER OBJECT This part implements WikiPlugin manager object of SuikaWiki WikiPlugin implementation model, second edition. =over 4 =item $p = SuikaWiki::Plugin->new (wiki => $WIKI) Constructs new instance of WikiPlugin manager =cut sub new ($%) { my $class = shift; my $self = bless {@_}, $class; $self; } =item $p->use_type ($type) Declares rules classified as $type is to be used. Even in current implementation this method makes no meaning, plugin callers must declare by this method for future compatibility. =cut sub use_type ($$) { #my ($self, $type) = @_; } =item $p->{rule}->{ $type }->{ $name } = { plugin rule definition } WikiPlugin rule @@TBD@@ =item $p->{wiki} Wiki implementation $p is associated with =back =head1 SEE ALSO suikawiki.pl, suikawiki-config.ph, =head1 LICENSE Copyright 2002-2003 Wakaba This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1; # $Date: 2003/10/18 07:08:34 $