ActionMap — modify existing or define custom Interchange actions
The directive allows creation of new (and modification of existing) Interchange ActionMaps using Perl subroutines.
If the action does not return a true value, Interchange processing will stop right there, allowing you to fully handle the request from your action.
See ActionMap glossary entry for more explanation and the list of built-in Interchange actionmaps.
Example: Replacing the Order action with a no-op
Put the following in catalog.cfg
:
ActionMap order sub { 1 }
Since we effectively turned Order into a no-operation action, the usual
order link such as
<A HREF="[area order/nextpage]">Order</a>
would be equivalent to [page nextpage]Order (does nothing)</a>
.
Example: Splitting a request into action map, page name and arguments
Here's an example of an actionmap "test
" that translates
HTTP requests in form of test/
into actual page requests to page
/arguments
page.html
with optional arguments
.
ActionMap test <<EOA sub { my $url = shift; # Remove actionmap name from the URL $url =~ s:^test/+::i; # Arguments are optional if ($url =~ s:/+(.*)$::) { $CGI->{mv_arg} = $1; } $CGI->{mv_nextpage} = $url; return 1; } EOA
For an introduction to Action Maps, see ActionMap glossary entry.
The standard process
ActionMap has a number of
configuration settings which can be controlled through FormAction
.
In the past, global ActionMaps had the action name stripped from the HTTP path. Beginning with Interchange 5.5, catalog and global ActionMaps are consistent in behavior and do not strip action name from the path.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 2161 (context shows lines 2161-2258)
sub parse_action { my ($var, $value, $mapped) = @_; if (! $value) { return $InitializeEmpty{$var} ? '' : {}; } return if $Vend::ExternalProgram; my $c; if($mapped) { $c = $mapped; } elsif(defined $C) { $c = $C->{$var} ||= {}; } else { no strict 'refs'; $c = ${"Global::$var"} ||= {}; } if (defined $C and ! $c->{_mvsafe}) { my $calc = Vend::Interpolate::reset_calc(); $c->{_mvsafe} = $calc; } my ($name, $sub) = split /\s+/, $value, 2; $name =~ s/-/_/g; ## Determine if we are in a catalog config, and if ## perl should be global and/or strict my $nostrict; my $perlglobal = 1; if($C) { $nostrict = $Global::PerlNoStrict->{$C->{CatalogName}}; $perlglobal = $Global::AllowGlobal->{$C->{CatalogName}}; } # Untaint and strip this pup $sub =~ s/^\s*((?s:.)*\S)\s*//; $sub = $1; if($sub !~ /\s/) { no strict 'refs'; if($sub =~ /::/ and ! $C) { $c->{$name} = \&{"$sub"}; } else { if($C and $C->{Sub}) { $c->{$name} = $C->{Sub}{$sub}; } if(! $c->{$name} and $Global::GlobalSub) { $c->{$name} = $Global::GlobalSub->{$sub}; } } if(! $c->{$name} and $AllowScalarAction{$var}) { $c->{$name} = $sub; } elsif(! $c->{$name}) { $@ = errmsg("Mapped %s action routine '%s' is non-existent.", $var, $sub); } } elsif ( ! $mapped and $sub !~ /^sub\b/) { if($AllowScalarAction{$var}) { $c->{$name} = $sub; } else { my $code = <<EOF; sub { return Vend::Interpolate::interpolate_html(<<EndOfThisHaiRYTHING); $sub EndOfThisHaiRYTHING } EOF $c->{$name} = eval $code; } } elsif ($perlglobal) { package Vend::Interpolate; if($nostrict) { no strict; $c->{$name} = eval $sub; } else { $c->{$name} = eval $sub; } } else { package Vend::Interpolate; $c->{$name} = $c->{_mvsafe}->reval($sub); } if($@) { config_warn("Action '%s' did not compile correctly (%s).", $name, $@); } return $c; }