Interchange supports multiple catalogs, and therefore splits its configuration
into two pieces. One is global, specified in interchange.cfg
, and affects every
catalog running under the same Interchange server installation.
The other — catalog part, is specified in each catalog's
CATROOT/catalog.cfg
, and has no effect on other catalogs.
Each configuration directive is accessible on global or catalog level,
or both. There's a special field named "DIRECTIVE TYPE
"
present in each directive's reference page, where you can look this up.
Keep in mind, however, that the directives on
global and catalog level don't have to be parsed by the same code —
in fact, they're mostly parsed by related but different code blocks.
Configuration directives are normally specified with the directive name as the first word on the line, with its value or values following. Capitalization of the directive name is not significant, but it helps readability and consistency. Additionally, any leading and trailing whitespace is removed ("stripped") before processing. Here's a simple example:
DirectiveName
value
Besides specifying directive values inline, one can conveniently use the following syntax to obtain value from external files:
DirectiveName
<include_filename
Note | |
---|---|
Note that this syntax can be used anywhere on a line, such as in
|
Files included from interchange.cfg
are relative to ICROOT. Files included
from catalog.cfg
are relative to specific catalog's CATROOT.
So-called "here document" syntax is supported as well. You can use it to spread directive values over several lines, with the usual Perl <<MARKER syntax (but unlike Perl, Interchange syntax uses no semicolon to terminate the marker). The closing marker must be the only thing on the line. No leading or trailing characters are allowed, not even whitespace. Here is a hypothetical directive using a here document:
DirectiveName
<<EODsetting1 setting2 setting3
EOD
The above is equivalent to:
DirectiveName
setting1 setting2 setting3
Other configuration files can also be included from the current one. For example, common settings can be defined in a single file:
include common.cfg
Or all files loaded from a directory:
include usertag/*
The familiar ifdef/endif
and ifndef/endif
pairs can be used to affect configuration processing:
Variable ORDERS_TO email_address ifdef ORDERS_TO ParseVariables Yes MailOrderTo ParseVariables No endif ifdef ORDERS_TO =~ /\@foo\.com$/ # Send all orders at foo.com to one place now # Set ORDERS_TO to stop default setting Variable ORDERS_TO 1 MailOrderTo orders@foo.com endif ifdef ORDERS_TO eq 'nobody@nowhere.com' # Better change to something else, set ORDERS_TO to stop default Variable ORDERS_TO 1 MailOrderTo someone@somewhere.com endif ifndef ORDERS_TO #Needs to go somewhere.... MailOrderTo webmaster@mydomain.local endif
It is possible to define configuration directives for the duration
of the block, using the <
notation:
DIRECTIVE
VALUE
> ... </DIRECTIVE
>
Variable HELLO Hello World! ParseVariables No Message Our greeting is: # Will print: Our greeting is: <ParseVariables Yes> Message Our greeting is the shiny # Will print: Our greeting is the shiny Hello World! </ParseVariables> Message Our greeting is back to: # Will print: Our greeting is back to:
Interchange, of course, offers a way to define variables. Variables defined
in your interchange.cfg
or catalog.cfg
can be referenced from both configuration files
themselves and the usual Interchange pages later, when the catalog is running.
Variables are defined using the Variable
directive (reading its
short reference now would be a good idea). The usual way to expand
a variable to it's value is to use the
__
notation.
This notation, however, is by default not enabled in RHS
("Right-Hand Side") values in configuration files. To enable it, use the
VARIABLE_NAME
__ParseVariables
directive which immediately affects the way
Interchange parses variables in config files. Here's an example to clarify
what we're talking about:
# Let's define two variables Variable SERVER_NAME myhost.mydomain.local Variable CGI_URL /cgi-bin/ic/tutorial # Let's make VendURL directive be a combination of and VendURL http:// # To your surprise, after the above, VendURL would literally contain # "http://". This is not what we want, so # we need to enable ParseVariables to achieve the desired effect: ParseVariables Yes VendURL http:// ParseVariables No # VendURL now contains "http://myhost.mydomain.local/cgi-bin/ic/tutorial"
It may come to you as a surprise, to learn that any configuration directive
can be "tied" to a Perl subroutine (if the Tie::Watch
Perl module is installed). This allows for a kind of triggers, watch points,
or numerous other interesting applications.
Similar to "here documents" ("<<
"), subroutine watches
are defined using the "<&
" notation. Consider the
following example:
MailOrderTo orders@myhost.mydomain.local MailOrderTo <&EOF sub { my($self, $default) = @_; if($Values->{special_handling}) { return 'vip@myhost.mydomain.local'; } else { return $default; } } EOF
When Interchange tries to retrieve the value of the MailOrderTo
configuration
directive (usually to e-mail out an order), our subroutine watch is called. In
turn, it returns a special value (a separate e-mail address) for customers
having value "special_handling
" defined in their
session. For the rest, it simply returns the default value.
Now that you've grasped the basics, there's more to the story.
From the above example, you see our watch subroutine was called in style
of &{$subref}(
.
"SELF
,
PREVIOUS_VALUE
)SELF
", meaning what it usually means in
Perl code, is a reference to the appropriate Tie::Watch
object. "PREVIOUS_VALUE
" is simply the previously
set value for a directive (usually its default). Those are the standard
two arguments we receive in a subroutine watch if the configuration directive
was of type SCALAR (defined to accept one string or text value).
Note | |
---|---|
Subroutine watches must be defined after the configuration directives have been set to their values. Setting values after subroutine watches will simply destroy them (the watches) and have unpredictable effects. |
If the configuration directive being watched was a list (type ARRAY), the
subroutine would be called in pattern
&{$subref}(
.
("SELF
,
INDEX
,
PREVIOUS_VALUE
)INDEX
" would be an array index of the
item accessed). Setting watch points on arrays that you don't control
completely is not recommended. (Namely, most Interchange subroutines call arrays
in their list context, and no access method is provided for that).
Finally, if the configuration directive watched was a hash (type HASH),
the subroutine would be called in pattern
&{$subref}(
.
("SELF
,
KEY
,
PREVIOUS_VALUE
)KEY
" would be a name of the
hash value accessed).
In the following example, we tie the Variable
configuration directive.
This is not recommended for performance reasons — Variable
directive is called very often and should not bear any extra overhead). But
it illustrates the power of this operation:
Variable TESTIT Unwatch worked. Variable <&EOV sub { my ($self, $key, $orig) = @_; if($key eq 'TESTIT') { # only the first time if($Scratch->{$key}++) { $self->Unwatch(); return $orig->{TESTIT}; } else { return "Tie::Watch works! -- name=$Values->{fname}"; } } else { return $orig->{$key}; } } EOV
The first time is called for an individual user,
it would return the string "
Tie::Watch works! -- name=
"
along with their first name (if they provided one at some point).
On a second access (again, for an individual user),
the watch would be dynamically dropped and the default value of the
variable NAME
TESTIT
returned.
All other variables would operate as usual.