package Gantry::Utils::CRON; use strict; use warnings; use HTML::TreeBuilder; use HTML::FormatText; use Gantry::Server; use Gantry::Engine::CGI; sub new { my ( $class, $opts ) = ( shift, shift ); my $self = {}; bless( $self, $class ); $self->set_controller( $opts->{controller} || undef ); $self->set_conf_instance( $opts->{conf_instance} || undef ); $self->set_conf_file( $opts->{conf_file} || undef ); $self->set_template_engine( $opts->{template_engine} || undef ); $self->set_namespace( $opts->{namespace} || undef ); # populate self with data from site return( $self ); } # end new sub run { my( $self, $opts ) = ( shift, shift ); die "missing controller" if ! $self->controller(); die "missing conf_instance" if ! $self->conf_instance(); die "missing conf_file" if ! $self->conf_file(); die "missing the controller method to call" if ! defined $opts->{method}; if ( $opts->{method} !~ /^do_/ ) { die "method must be a do_* method"; } my @imports; push( @imports, "-Engine=CGI", ( "-TemplateEngine=" . $self->template_engine() ), ); push( @imports, ( "-PluginNamespace=" . $self->namespace() ), ) if $self->namespace(); my $app_module = $self->controller() . " qw{ " . join( ' ', @imports ) . " }"; eval "use $app_module"; if ( $@ ) { die $@; } my $cgi = Gantry::Engine::CGI->new( { config => { GantryConfInstance => $self->conf_instance, GantryConfFile => $self->conf_file, }, locations => { '/' => $self->controller(), }, } ); my $server = Gantry::Server->new(); $server->set_engine_object( $cgi ); my $action = $opts->{method}; $action =~ s/^do_//; my @uri_parts = (); my @param_pairs = (); push( @uri_parts, $action ); push( @uri_parts, @{ $opts->{args} } ); for my $p ( keys %{ $opts->{params} } ) { next if ! defined $opts->{params}{$p}; push( @param_pairs, join( '=', $p, $opts->{params}{$p} ) ); } my $uri = '/' . join( '/', @uri_parts ); if ( scalar( @param_pairs ) > 0 ) { $uri .= '?' . join( '&', @param_pairs ); } # set the proper gantry request call my $gantry_method_call = 'handle_request_test_post'; if ( $opts->{type} eq 'get' ) { $gantry_method_call = 'handle_request_test'; } my( $status, $content ) = $server->$gantry_method_call( $uri ); my $tree = HTML::TreeBuilder->new_from_content( $content ); my $formatter = HTML::FormatText->new( leftmargin => 0, rightmargin => 55 ); my $text_content = $formatter->format( $tree ); $tree->delete; # required to properly free memory $self->set_status( $status ); $self->set_content( $text_content ); return( $status, $text_content ); } # content accessors sub set_content { my( $self, $p ) = @_; $self->{_content} = $p; } sub content { my( $self ) = @_; return $self->{_content}; } # status accessors sub set_status { my( $self, $p ) = @_; $self->{_status} = $p; } sub status { my( $self ) = @_; return $self->{_status}; } # controller accessors sub set_controller { my( $self, $p ) = @_; $self->{_controller} = $p; } sub controller { my( $self ) = @_; return $self->{_controller}; } # conf instance accessors sub set_conf_instance { my( $self, $p ) = @_; $self->{_conf_instance} = $p; } sub conf_instance { my( $self ) = @_; return $self->{_conf_instance}; } # conf file accessors sub set_conf_file { my( $self, $p ) = @_; $self->{_conf_file} = $p; } sub conf_file { my( $self ) = @_; return $self->{_conf_file} || '/etc/gantry.conf'; } # template engine accessors sub set_template_engine { my( $self, $p ) = @_; $self->{_template_engine} = $p; } sub template_engine { my( $self ) = @_; return $self->{_template_engine} || 'TT'; } # plugin namespace accessors sub set_namespace { my( $self, $p ) = @_; $self->{_namespace} = $p; } sub namespace { my( $self ) = @_; return $self->{_namespace}; } # EOF 1; __END__ =head1 NAME Gantry::Utils::CRON - a way to call a controller's method from a CRON script =head1 SYNOPSIS use strict; use warnings; use Gantry::Utils::CRON; my $cron = Gantry::Utils::CRON->new( { controller => 'Apps::RR::InvoiceMunger::Batch', conf_instance => 'apps_rr_invoicemunger_dev_prod', conf_file => '/etc/gantry.conf', # optional template_engine => 'TT', # optional namespace => 'Apps::RR::InvoiceMunger', # optional } ); # alternative setters $cron->set_controller( 'Apps::RR::InvoiceMunger::Batch' ); $cron->set_conf_instance( 'invoice_munger_prod' ); $cron->set_conf_file( '/etc/gantry.conf' ); $cron->set_template_engine( 'TT' ); $cron->set_namespace( 'mynamespace' ); $cron->run( { method => 'do_process_files', # do_* required args => [ '1', '2' ], # optional params => { confirm => 1, test => 3 } # optional type => 'post' # or 'get' -- optional } ); print STDERR $cron->status(); print STDERR $cron->content(); =head1 DESCRIPTION This module is a utility to run a Gantry do_ method from a CRON script =head1 METHODS =over 4 =item new( {} ); Standard constructor, call it first. Required controller - Gantry controller that contains the do_ method conf_instance - Gantry conf instance name Optional conf_file - defaults to '/etc/gantry.conf' template_engine - defaults to 'TT' namespace =item run( {} ) This method executes the defined controller's do_ method. Accepts method - the do_ method args - array of args to be passed to the method params - hashref of params to be passed to method type - 'get' or 'post' defaults to 'post' Returns status - page status code content - plain-text version of method's returned content =item set_content setter for the returned content =item content getter for the returned content =item set_status setter for the returned status =item status getter for the returned status =item set_controller setter for controller =item controller getter for controller =item set_conf_instance setter for the Gantry conf_instance =item conf_instance getter for the Gantry conf_instance =item set_conf_file setter for the Gantry conf_file. =item conf_file getter for the Gantry conf_file. Defaults to /etc/gantry.conf =back =head1 SEE ALSO Gantry(3) =head1 LIMITATIONS This module depends on Gantry(3), HTML::TreeBuilder, HTML::FormatText =head1 AUTHOR Tim Keefer =head1 COPYRIGHT and LICENSE Copyright (c) 2007, Tim Keefer. This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.6 or, at your option, any later version of Perl 5 you may have available. =cut