CGI-Kwiki

 view release on metacpan or  search on metacpan

lib/CGI/Kwiki.pm  view on Meta::CPAN

package CGI::Kwiki;
$VERSION = '0.18';
@EXPORT = qw(attribute);
@CHAR_CLASSES = qw($ADMIN $UPPER $LOWER $ALPHANUM $WORD $WIKIWORD);
@EXPORT_OK = (@CHAR_CLASSES, qw(encode decode escape unescape));
%EXPORT_TAGS = (char_classes => [@CHAR_CLASSES]);

use strict;
use base 'Exporter';
use CGI qw(-no_debug);

use vars qw($ADMIN);
$ADMIN ||= 0;

use vars qw($UPPER $LOWER $ALPHANUM $WORD $WIKIWORD);
if ($] < 5.008) {
    $UPPER    = "A-Z\xc0-\xde";
    $LOWER    = "a-z\xdf-\xff";
    $ALPHANUM = "A-Za-z0-9\xc0-\xff";
    $WORD     = "A-Za-z0-9\xc0-\xff_";
    $WIKIWORD = $WORD;
}
else {
    $UPPER    = '\p{UppercaseLetter}';
    $LOWER    = '\p{LowercaseLetter}';
    $ALPHANUM = '\p{Letter}\p{Number}';
    $WORD     = '\p{Letter}\p{Number}\p{ConnectorPunctuation}';
    $WIKIWORD = "$UPPER$LOWER\\p{Number}\\p{ConnectorPunctuation}";
}

# All classes defined by CGI::Kwiki
sub classes {
    qw(
        new
        config
        config_yaml
        driver
        cgi
        cookie
        database
        metadata
        backup
        display
        edit
        formatter
        template
        plugin
        search
        changes
        prefs
        pages
        slides
        javascript
        style
        scripts
        blog
        i18n
        import
    )
}

# Traditional CGI runner
sub run_cgi {
    eval "use CGI::Carp qw(fatalsToBrowser)";
    die $@ if $@;

    my $cgi_class = (eval { require CGI::Fast; 1 } ? 'CGI::Fast' : 'CGI');
    while (my $cgi = $cgi_class->new) {
        my $driver = load_driver();
        $CGI::Kwiki::user_name = 
            $ENV{REMOTE_USER} || 
                CGI->remote_host();
        my $html = $driver->drive;
        if (ref $html) {
            print CGI::redirect($html->{redirect});
        } else {
            my $header = $driver->cookie->header;
            $driver->encode($header);
            $driver->encode($html);
            print $header, $html;
        }
	last if $cgi_class eq 'CGI';
    }
}

# Speedy mod_perl runner
sub handler {
    my ($r) = @_;
    my $base_directory = $r->location;
    chdir($base_directory) 
      or die "Can't chdir to '$base_directory'\n";
    eval "use Apache::Constants qw(OK REDIRECT)";
    die $@ if $@;

    my $driver = load_driver();
    $CGI::Kwiki::user_name = 
      $ENV{REMOTE_USER} ||
      $r->get_remote_host || 
      $r->connection->remote_ip;
    my $html = $driver->drive;
    if (ref $html) {
        $r->method('GET');
        $r->headers_in->unset('Content-length');
        $r->header_out('Location' => $html->{redirect});
        $r->status(&REDIRECT);
        $r->send_http_header;
    }
    else {
        $r->print($driver->cookie->header, $html);
        $r->status(&OK);
    }
    return;
}

# A generic class attribute set/get method generator
sub attribute {
    my ($attribute) = @_;
    my $pkg = caller;
    no strict 'refs';
    local $SIG{__WARN__} = sub {}; # shut up 'redefined' warnings
    *{"${pkg}::$attribute"} =
      sub {
          my $self = shift;
          return $self->{$attribute} unless @_;
          $self->{$attribute} = shift;
          return $self;
      };
}

# The most basic attributes inherited by almost all classes
attribute 'driver';
attribute 'config';
attribute 'cgi';
attribute 'plugin';
attribute 'template';
attribute 'formatter';
attribute 'database';
attribute 'metadata';
attribute 'backup';
attribute 'prefs';
attribute 'i18n';

# Constructor inherited by most classes
sub new {
    my ($class, $driver) = @_;
    my $self = bless {}, $class;
    $self->driver($driver);
    $self->config($driver->config);
    $self->cgi($driver->cgi);
    $self->plugin($driver->plugin);
    $self->template($driver->template);
    $self->formatter($driver->formatter);
    $self->database($driver->database);
    $self->metadata($driver->metadata);
    $self->backup($driver->backup);
    $self->prefs($driver->prefs);
    return $self;
}

sub load_driver {
    require CGI::Kwiki::Config;
    my $config = CGI::Kwiki::Config->new;
    my $driver_class = $config->driver_class;
    eval qq{ require $driver_class }; die $@ if $@;
    my $driver = $driver_class->new($config);
    $config->driver($driver);
    return $driver;
}

# I run a development Kwiki in the mykwiki/ subdirectory of CGI-Kwiki's
# development directory. I edit all the data files and templates in
# there, and then I use this rebuild method to pack them into the DATA
# sections of their respective modules.
sub rebuild {
    my $filename = $0;
    my $module = $filename;
    $module =~ s/.*lib\/(?=CGI)//;
    $module =~ s/\.pm$//;
    $module =~ s/\//::/g;
    my $self = $module->new(load_driver);
    my $data = '';
    my ($directory) = $self->directory;
    for my $file (sort glob("mykwiki/$directory/*")) {
        my $label = $file;
        $label =~ s/.*\///;
        $label =~ s/\.\w+$//;
        next if $label =~ /^%/; # XXX exclude Chinese pages
        $data .= "__${label}__\n";
        open FILE, $file or die $!;
        $data .= do {local $/; <FILE>};
        close FILE;
    }
    $data =~ s/^=/^=/gm;
    open MODULE, $filename
      or die $!;
    my $module_text = do {local $/;<MODULE>};
    close MODULE;
    unless ($module_text =~ /^(.*__DATA__\n.*=cut\n\n)/s) {
        die "Can't parse $filename\n";
    }
    $module_text = $1 . $data;
    open MODULE, "> $filename"
      or die "Can't open $filename of output:\n$!";
    print MODULE $module_text;
    close MODULE;
    print "$filename updated\n";
    exit 0;
}

# Support for unpacking the DATA files attached to many CGI::Kwiki classes
sub create_files {
    my ($self) = @_;
    umask 0000;
    my $package = ref($self);
    my @files = split /^__([$WORD\/]+)__\n/m, $self->data;



( run in 0.568 second using v1.01-cache-2.11-cpan-d8267643d1d )