[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: [cgiapp] Proposed patch to CGI::Application


The CGI::Application documentation proposes a solution that makes sense :
override 'load_tmpl( )' method to behave however you want it to.

FROM THE POD:
-------------
If your application requires more specialized behavior than this, you are
encoraged[sic] to override load_tmpl() by implementing your own load_tmpl()
in your CGI::Application sub-class application module.
-------------



Here at O'Neil, we search through a list of 6-10 dynamic template locations
looking for the file we need, and everywhere we need  a file we call
'load_tmpl( 'my_tmpl.html' );' and our 'load_tmpl( )' method finds the
correct template for us.

Also, wouldn't this patch break existing implementations?


Thanks,

Cory Trese
Lead Web Application Developer

O'NEIL & ASSOCIATES, INC.
495 Byers Rd.
Miamisburg, Ohio 45342-3662
Phone: (937) 865-0800 ext. 3038
Fax: (937) 865-5858
E-mail: suppressed


-----Original Message-----
From: Chris Brooks [mailto:suppressed
Sent: Wednesday, April 09, 2003 1:17 PM
To: suppressed
Subject: [cgiapp] Proposed patch to CGI::Application


Hi all,

I would like to propose the following patch for inclusion in
CGI::Application.  Essentially, the patch gives you a new interface to
the @extra_params array that is passed to HTML::Template::new_file from
CGI::Application::load_tmpl.    It allows you to push a path onto the
end of this array, instead of unshifting it onto the beginning (the
current default behavior).

Here's the scenario that I needed it for:

I have an application (call it MyApp) that subclasses CGI::Application.
The application has 7 templates that are displayed in the various run
modes.  I have several clients that use the application, and each client
is allowed to define customized text to appear on each of the 7
templates.  The directory structure for the templates is as follows:

/path/to/templates/
   |_ default/
          |_ tmpl_a.tmpl
          |_ ...
          |_ tmpl_g.tmpl
   |_ client_1/
          |_ tmpl_d.tmpl
   |_ ...
   |_ client_n/
          |_ tmpl_a.tmpl
          |_ ...
          |_ tmpl_g.tmpl

All clients access MyApp through myscript.pl, and myscript.pl figures
out which template directory the client wants, and passes the path to
that directory as a param to new():

my $app = MyApp->new( TMPL_PATH => $path_to_directory );

The trick is that if client_1 does not have custom text for a particular
template, I don't duplicate the template -- I just fall back to the
template with the same name in the default directory.  Consider the
scenario where an end user for client_1 requests the template
tmpl_a.tmpl.  This patch allows me to define the "fall back" or default
directory in the setup() method with a single additional method call,
like this:

$self->default_tmpl_path( '/path/to/templates/default' );

Now, when load_tmpl() calls HTML::Template::new_file(), it passes two
directories:

/path/to/templates/client_1
/path/to/templates/default

HTML::Template will look for tmpl_a.tmpl in client_1/ and if it isn't
present, it will use the version in default/.

I could have implemented this by passing the default path as part of the
@extra_params array that gets passed to load_tmpl(), but this seems
redundant (and potentially error prone, since you need to manually
maintain the correct order in the arrayref that you pass to load_tmpl()
-- in 7 places, in my case).  The patch that follows allows me to define
this directory in one place, and be done with it.

Thoughts?

(I did a context diff to generate the patch, so there's quite a bit of
text.  I did a minimal patch to the documentation as well, and there is
a brief test script at the end.)

Thanks,
Chris

*** /usr/lib/perl5/site_perl/5.005/CGI/Application.pm   Sat Feb  1
02:46:11 2003
--- CGI/Application.pm  Wed Apr  9 09:38:21 2003
***************
*** 325,344 ****
       my $self = shift;
       my ($tmpl_file, @extra_params) = @_;

!       # add tmpl_path to path array of one is set, otherwise add a
path arg
!       if (my $tmpl_path = $self->tmpl_path) {
!               my $found = 0;
!               for( my $x = 0; $x < @extra_params; $x += 2 ) {
!                       if ($extra_params[$x] eq 'path' and
!                           ref $extra_params[$x+1]     and
!                           ref $extra_params[$x+1] eq 'ARRAY') {
!                               unshift @{$extra_params[$x+1]}, $tmpl_path;
!                               $found = 1;
!                               last;
!                       }
!               }
!           push(@extra_params, path => [ $tmpl_path ]) unless $found;
!       }

       require HTML::Template;
       my $t = HTML::Template->new_file($tmpl_file, @extra_params);
--- 325,331 ----
       my $self = shift;
       my ($tmpl_file, @extra_params) = @_;

!         @extra_params = $self->munge_extra_params( @extra_params );

       require HTML::Template;
       my $t = HTML::Template->new_file($tmpl_file, @extra_params);
***************
*** 347,352 ****
--- 334,362 ----
 }


+ #I have split this out into its own method to simplify testing
+
+ sub munge_extra_params {
+     my $self = shift;
+     my %extra_params = @_;
+     my $default_tmpl = $self->default_tmpl_path();
+
+     # add tmpl_path to path array of one is set, otherwise add a path arg
+     if (my $tmpl_path = $self->tmpl_path) {
+         if ( ref $extra_params{ 'path' } eq 'ARRAY' ) {
+           unshift @{ $extra_params{ 'path' } }, $tmpl_path;
+           push @{ $extra_params{ 'path' } }, $default_tmpl;
+       }
+       else { $extra_params{ 'path' } = [ $tmpl_path, $default_tmpl ] }
+     }
+     else {
+         if ( ref $extra_params{ 'path' } eq 'ARRAY' ) { push @{
$extra_params{ 'path' } }, $default_tmpl }
+       else { $extra_params{ 'path' } = [ $default_tmpl ] }
+     }
+     return %extra_params;
+ }
+
+
 sub mode_param {
       my $self = shift;
       my ($mode_param) = @_;
***************
*** 488,493 ****
--- 498,520 ----
 }


+ sub default_tmpl_path {
+       my $self = shift;
+       my ($default_path) = @_;
+
+       # First use?  Create new __DEFAULT_TMPL_PATH!
+       $self->{__DEFAULT_TMPL_PATH} = '' unless
(exists($self->{__DEFAULT_TMPL_PATH}));
+
+       # If data is provided, set it!
+       if (defined($default_path)) {
+               $self->{__DEFAULT_TMPL_PATH} = $default_path;
+       }
+
+       # If we've gotten this far, return the value!
+       return $self->{__DEFAULT_TMPL_PATH};
+ }
+
+
 sub prerun_mode {
       my $self = shift;
       my ($prerun_mode) = @_;
***************
*** 899,904 ****
--- 926,932 ----
     start_mode() - text scalar containing the default run mode.
     run_modes() - hash table containing mode => function mappings.
     tmpl_path() - text scalar containing path to template files.
+     default_tmpl_path() - text scalar containing path to default
template files.

 Your setup() method may call any of the instance methods of your
application.
 This function is a good place to define properties specific to your
application
***************
*** 909,914 ****
--- 937,943 ----
       sub setup {
               my $self = shift;
               $self->tmpl_path('/path/to/my/templates/');
+               $self->default_tmpl_path('/path/to/default/templates/');
               $self->start_mode('putform');
               $self->run_modes({
                       'putform'  => 'my_putform_func',
***************
*** 1109,1117 ****
 is used for create the object.  Refer to L<HTML::Template> for specific
usage
 of HTML::Template.

! If tmpl_path() has been specified, load_tmpl() will set the
! HTML::Template C<path> option to the path provided.  This further
! assists in encapsulating template usage.

 The load_tmpl() method will pass any extra paramaters sent to it
directly to
 HTML::Template->new_file().  This will allow the HTML::Template object
to be
--- 1138,1149 ----
 is used for create the object.  Refer to L<HTML::Template> for specific
usage
 of HTML::Template.

! If tmpl_path() has been specified, load_tmpl() will unshift this value
onto
! the beginning of the array of paths passed to the HTML::Template
C<path> option.
! If you want to push a path onto the end of the array of paths passed
to the
! HTML::Template C<path> option, call default_tmpl_path() in your setup()
! method and pass it your default path. This further assists in
encapsulating
! template usage.

 The load_tmpl() method will pass any extra paramaters sent to it
directly to
 HTML::Template->new_file().  This will allow the HTML::Template object
to be

======================================
And here is the test script that I'm running to make sure that
munge_tmpl_path() returns correctly:

#!/usr/bin/perl
use lib qw( . );

use strict;
use Test::More tests => 12;

BEGIN { use_ok( 'CGI::Application' ) }


my $default_path = '/www/perl/templates/';
my $app = CGI::Application->new;
isa_ok( $app, 'CGI::Application' );
is( $app->default_tmpl_path( $default_path ), $default_path, 'Checking
that default_tmpl_path() returns correctly' );
undef $app;

#Test by passing TMPL_PATH to new(), with no conflicts
$app = CGI::Application->new( TMPL_PATH => $default_path );
my %extra_params = $app->munge_extra_params;
is( $extra_params{ path }->[0], $default_path, 'Checking
munge_extra_params()' );
undef $app;

#Test with no params to new(), but calling default_tmpl_path()
$app = CGI::Application->new;
$app->default_tmpl_path( $default_path );
my %extra_params = $app->munge_extra_params;
is( $extra_params{ path }->[0], $default_path, 'Checking
munge_extra_params()' );
undef $app;

#Test with a default path and a path specified through new()
my $new_path = '/www/perl/templates/different';
my $app = CGI::Application->new( TMPL_PATH => $new_path, );
$app->default_tmpl_path( $default_path );

%extra_params = $app->munge_extra_params;
is( $extra_params{ path }->[0], $new_path, 'Checking
munge_extra_params()' );
is( $extra_params{ path }->[1], $default_path, 'Checking
munge_extra_params()' );
undef $app;

#Test by passing a path to load_tmpl as part of @extra_params
my $app = CGI::Application->new;
$app->default_tmpl_path( $default_path );
%extra_params = $app->munge_extra_params( path => [ $new_path ] );
is( $extra_params{ path }->[0], $new_path, 'Checking
munge_extra_params()' );
is( $extra_params{ path }->[1], $default_path, 'Checking
munge_extra_params()' );
undef $app;

#Test by passing a path to load_tmpl as part of @extra_params
my $yadp = '/www/perl/templates/yet_another_different_path/';
my $app = CGI::Application->new( TMPL_PATH => $new_path );
$app->default_tmpl_path( $default_path );
%extra_params = $app->munge_extra_params( path => [ $yadp ] );
is( $extra_params{ path }->[0], $new_path, 'Checking
munge_extra_params()' );
is( $extra_params{ path }->[1], $yadp, 'Checking munge_extra_params()' );
is( $extra_params{ path }->[2], $default_path, 'Checking
munge_extra_params()' );
undef $app;



---------------------------------------------------------------------
Web Archive:  http://www.mail-archive.com/suppressed/
To unsubscribe, e-mail: suppressed
For additional commands, e-mail: suppressed


---------------------------------------------------------------------
Web Archive:  http://www.mail-archive.com/suppressed/
To unsubscribe, e-mail: suppressed
For additional commands, e-mail: suppressed


Mail converted by mhonarc 2.6.15
This archive provided courtesy of JSW4.NET, Internet Hosting Services for Small Business.