Sam,
   I'm working from the standpoint of not making
associate any more complex, actually less so from the
end user standpoint. If you look at the code all I've
done is added three checks for
($associated_object->can('param') &&
$option{associate_by_methods}), their associated
blocks of code (which are duplicates of existing) and
a 17 line function to lookup the methods. The thought
of instantiating another object to do what can be done
in a few lines of code internally seems far more
complex to me. This should also be a boost in
performance as you are going directly against the
object's methods rather than a layer of indirection
that param creates. If a new function is created in my
object I only need add the TMPL_VAR to the .tmpl
without the need to add support for it to a param
method. Of course all of the existing param
functionalty will still work as is, so I'm not
suggesting a rework of what is already there, just a
great deal more flexibility from a small bit of code.

   
diff -u output (pod included):
   
---
/usr/local/lib/perl5/site_perl/5.8.4/HTML/Template.pm
2004-06-18 13:42:06.000000000 -0400
+++ ./Template.pm       2005-02-11 14:33:42.998984000 -0500
@@ -712,6 +712,28 @@
 
 =item *
 
+associate_by_methods - this will force HTML::Template
to look at an objects 
+methods and retrieve data from them rather than via
param (i.e., associated 
+object does not need to define param). This should
maintain backwards 
+compatibility with existing param use.
+
+=item *
+
+associate_by_methods_respect_privacy - this is a
prefix that will be looked 
+for when examining object methods, if found then
those methods will not be 
+useable in the template. Setting to 1 will cause the
default of '_' to be 
+used. This allows you to actually keep private
methods private: 
+   
+   my $template = HTML::Template->new(filename =>
'template.tmpl',
+                                     associate =>
[$query, $other_obj],
+                                    
associate_by_methods => 1,
+                                    
associate_by_methods_respect_privacy => 1);
+   
+   $other_obj->_some_private_method(); #
'_some_private_method' is NOT a TMPL_VAR
+   $other_obj->some_public_method();   #
'some_public_method' is a TMPL_VAR
+
+=item *
+
 case_sensitive - setting this option to true causes
HTML::Template to
 treat template variable names case-sensitively.  The
following example
 would only set one parameter without the
"case_sensitive" option:
@@ -2538,6 +2560,36 @@
   }
 }
 
+# This accepts an object or package name and will
return a list of methods
+#
+#  $self->_get_object_methods('HTML::Template',1)
+#      would return
['associateCGI','carp','clear_params','confess','croak','md5_hex','new','new_array_ref','new_file','new_filehandle','new_scalar_ref','output','param','query']
+#
+#  Params:
+#     pkg - either an object or package/module name
to be examined
+#     respect_private - This is a prefix to hide
private methods from the list.
+#                       Defaults to '_' if set to 1.
TODO://let a regex be passed
+#
+# Based on function and symTable from
http://search.cpan.org/~mpocock/MRP-1.0/MRP/Introspection.pm
+#
+sub _get_object_methods {
+  my $self = shift;
+  my $pkg = shift;
+  my $respect_private = shift; # won't return methods
beginning with an this value, '_' by default
+  $respect_private = '_' if($respect_private == 1);
+  $pkg = (ref $pkg || $pkg) . '::';
+  
+  my @methods;
+  my ($name, $glob);
+  
+  no strict 'refs'; 
+  while(($name, $glob) = each %{\%$pkg}) {
+    defined (*$glob{CODE}) && do { push @methods,
$name unless($respect_private && $name =~
/^$respect_private/) };
+  }
+
+  return @methods;
+}  
+
 
 # obsolete implementation of associate
 sub associateCGI { 
@@ -2600,36 +2652,56 @@
   # globalize vars - this happens here to localize
the circular
   # references created by global_vars.
   $self->_globalize_vars() if
($options->{global_vars});
-
-  # support the associate magic, searching for
undefined params and
-  # attempting to fill them from the associated
objects.
+                                 
   if (scalar(@{$options->{associate}})) {
-    # prepare case-mapping hashes to do
case-insensitive matching
+   # prepare case-mapping hashes to do
case-insensitive matching
     # against associated objects.  This allows CGI.pm
to be
     # case-sensitive and still work with asssociate.
     my (%case_map, $lparam);
     foreach my $associated_object
(@{$options->{associate}}) {
       # what a hack!  This should really be optimized
out for case_sensitive.
-      if ($options->{case_sensitive}) {
-        map {
-          $case_map{$associated_object}{$_} = $_
-        } $associated_object->param();
-      } else {
-        map {
-          $case_map{$associated_object}{lc($_)} = $_
-        } $associated_object->param();
+      if ($associated_object->can('param') &&
!$options->{associate_by_methods}) {       
+         if ($options->{case_sensitive}) {
+           map {
+             $case_map{$associated_object}{$_} = $_
+           } $associated_object->param();
+         } else {
+           map {
+             $case_map{$associated_object}{lc($_)} =
$_
+           } $associated_object->param();
+         }
+      } else { ### get the object's methods          
 
+         if ($options->{case_sensitive}) {
+           map {
+             $case_map{$associated_object}{$_} = $_
+           }
$self->_get_object_methods($associated_object,$options->{associate_by_methods_respect_privacy});
+         } else {
+           map {
+             $case_map{$associated_object}{lc($_)} =
$_
+           }
$self->_get_object_methods($associated_object,$options->{associate_by_methods_respect_privacy});
+         }
       }
+      
     }
 
     foreach my $param (keys %{$self->{param_map}}) {
       unless (defined($self->param($param))) {
       OBJ: foreach my $associated_object (reverse
@{$options->{associate}}) {
-          $self->param($param, scalar
$associated_object->param($case_map{$associated_object}{$param})),
last OBJ
-            if
(exists($case_map{$associated_object}{$param}));
+                              
+          if ($associated_object->can('param') &&
!$options->{associate_by_methods}) { ### 
+            print STDERR "\n".
ref($associated_object) . "::param('" .
$case_map{$associated_object}{$param} . "');\n";
+            $self->param($param, scalar
$associated_object->param($case_map{$associated_object}{$param})),
last OBJ
+               if
(exists($case_map{$associated_object}{$param}));
+          } else {            
+             my $method =
$case_map{$associated_object}{$param};
+             $self->param($param, scalar
$associated_object->$method), last OBJ
+               if
(exists($case_map{$associated_object}{$param}));      
     
+          }
+            
         }
       }
     }
-  }
+  } 
 
   use vars qw($line @parse_stack); local(*line,
*parse_stack);
 
@@ -3331,3 +3403,4 @@
   USA
 
 =cut
+



--- Sam Tregar <[EMAIL PROTECTED]> wrote:

> On Fri, 11 Feb 2005, Scottsweep wrote:
> 
> >    I want to propose the following PATCH to
> > HTML::Template. This would allow objects to be
> > associated without the need to define a param
> method
> > (all public methods can be TMPL_VARs). 
> 
> This seems like a reasonable thing to want, but I
> think it would be
> better done with a wrapper object.  Imagine:
> 
>   use HTML::Template;
>   use Class::ParamWrapper;
> 
>   my $t = HTML::Template->new(filename  => $foo,
>                               associate =>
> Class::ParamWrapper->new($some_object));
> 
> Class::ParamWrapper would provide a param() method
> which proxies calls
> to the wrapped object.  You can add any
> configuration you need to the
> Class::ParamWrapper->new() call.
> 
> This has the benefit of not increasing the
> complexity of
> HTML::Template's associate implementation which is
> already pretty
> unmanageable.  It also opens up your code to use in
> other contexts.
> 
> -sam
> 
> PS: If you want to submit a patch in the future
> please prepare it
> using 'diff -u'.
> 



                
__________________________________ 
Do you Yahoo!? 
Yahoo! Mail - Helps protect you from nasty viruses. 
http://promotions.yahoo.com/new_mail


-------------------------------------------------------
SF email is sponsored by - The IT Product Guide
Read honest & candid reviews on hundreds of IT Products from real users.
Discover which products truly live up to the hype. Start reading now.
http://ads.osdn.com/?ad_id=6595&alloc_id=14396&op=click
_______________________________________________
Html-template-users mailing list
Html-template-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/html-template-users

Reply via email to