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/argumentspage.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.
For catalog-level ActionMaps, Interchange does not strip the actionmap nam from the requested HTTP path; for global ActionMaps it does. See the section called “EXAMPLES”.
Interchange 5.7.0:
Source: lib/Vend/Config.pm
Line 2134 (context shows lines 2134-2213)
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;
# Untaint and strip this pup
$sub =~ s/^\s*([\000-\377]*\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 (! $C or $Global::AllowGlobal->{$C->{CatalogName}}) {
package Vend::Interpolate;
$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;
}