/
SpecialSub
283 lines (261 loc) · 8.98 KB
/
SpecialSub
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
__NAME__ purpose
specify Perl subroutines to handle certain events or conditions
__END__
__NAME__ synopsis
<arg choice='plain'><replaceable>event_name</replaceable></arg>
<arg choice='plain' rep='repeat'><replaceable>subroutine_name</replaceable></arg>
__END__
__NAME__ description
<para>
The directive specifies &PERL; subroutines that should be called to
handle certain events. The available events are described below.
</para>
<refsect2>
<title>Request (<literal>request_init</literal>)</title>
<para>
Event triggered on every request, right after catalog
selection and before &glos-session; assignment.
</para>
</refsect2>
<refsect2>
<title>Request (<literal>admin_init</literal>)</title>
<para>
Event triggered on every request for users with administrator privileges,
request, after initialization of embedded Perl objects. This allows
&glos-catalog; subroutines to be specified as request handlers and have
properly initialized &glos-session; variables by the time they run.
</para>
</refsect2>
<refsect2>
<title>Debug Qualify (<literal>debug_qualify</literal>)</title>
<para>
Event triggered to determine whether &glos-debug; mode should be
enabled for the incoming client connection. Have in mind that simple,
host-based decision can be made by using the &conf-DebugHost;
configuration directive. The <literal>debug_qualify</literal>
specialSub is invoked only if &conf-DebugHost; is either undefined,
or the client host is found in the &conf-DebugHost; list.
See &glos-debug; glossary entry for a complete discussion.
</para>
</refsect2>
<refsect2>
<title>Flypage (<literal>flypage</literal>)</title>
<para>
Event triggered for determining the result set for the flypage.
<!-- TODO more info -->
</para>
</refsect2>
<refsect2>
<title>Credit Card Type (<literal>guess_cc_type</literal>)</title>
<para>
Event triggered at the time
of deriving credit card type, &var-MV_CREDIT_CARD_TYPE;.
&IC; already recognizes
major credit card types but local areas might require you to
write custom recognition code.
The subroutine is called with the credit card number.
A &glos-true; return value should contain the recognized credit card
type name.
A &glos-false; value indicates that the number recognition did not
suceed, and that &IC; should proceed with its built-in detection
algorithm.
</para>
</refsect2>
<refsect2>
<title>Session Creation (<literal>init_session</literal>)</title>
<para>
Event triggered at new &glos-session; creation time.
The subroutine is called with the pointer to the newly created
&glos-session; variables space. Subroutine return value is not used.
</para>
</refsect2>
<refsect2>
<title>Lockout (<literal>lockout</literal>)</title>
<para>
Event triggered for locking out a bad web spider or misbehaving
client (see &conf-RobotLimit;). The subroutine is called without
parameters and is expected to perform all the necessary custom
steps. It should exit with an appropriate return value to signal
how the rest of the process should be handled.
</para>
<para>
A &glos-true; return value indicates that no more handling is
needed. A &glos-false; value indicates that &IC; should continue
and execute the default, built-in action lockout action, which
is specified by the &conf-LockoutCommand; config directive.
<!-- TODO : Where do you read IP or something from ? -->
</para>
</refsect2>
<refsect2>
<title>Missing page (<literal>missing</literal>)</title>
<para>
Event triggered when a requested &IC; page is missing.
The subroutine is called with the name of the missing page
and is expected to perform all the necessary custom handling.
It should exit with an appropriate return value to signal
how the rest of the process should be handled.
</para><para>
A &glos-true; return
value will indicates that all actions (including the response to the client)
have been performed by your function and no more handling is needed.
You can also return an array, (1, <replaceable>PAGENAME</replaceable>), where
<replaceable>PAGENAME</replaceable> is the page to be displayed to the user.
</para><para>
A &glos-false; return value indicates that &IC; should continue
and execute the default, built-in action, which
is displaying a page specified by "&conf-SpecialPage;
<literal>missing</literal>".
</para>
</refsect2>
<refsect2>
<title>Shipping calculation (<literal>shipping_callout</literal>)</title>
<para>
Event is triggered after shipping calculation, but before result is
formatted and returned.
</para>
<para>
It's useful for
the type of customization that would require modifying too many shipping
table entries or using entirely custom shipping code, because it allows
you to build on the powerful shipping features interchange already has.
</para>
</refsect2>
<refsect2>
<title>Weight calculation (<literal>weight_callout</literal>)</title>
<para>
Event is triggered after weight is processed for shipping calculation.
</para>
The subroutine is called with the weight as parameter and expects the modified weight as return value.
<para>
It does not affect other calculations, such as done by the <tag>weight</tag>
usertag.
</para>
</refsect2>
__END__
__NAME__ notes
If the examples above, the &PERL; subroutines have been defined on a
&glos-catalog; level, using &conf-Sub; configuration directive.
&IC; catalogs (and everything configured within them) are subject to
&glos-safe; restrictions, so your &conf-Sub; blocks might have
insufficient permissions to execute all of your commands. To solve that
problem, either relax the restrictions by using &conf-SafeUntrap;,
or define the subroutines at the global level (in &gcf;) using
unrestricted &conf-GlobalSub;s.
</para><para>
As a misnomer, SpecialSub <literal>catalog_init</literal> was
renamed to <literal>request_init</literal> in &IC; 5.5.2.
__END__
__NAME__ example: Defining "SpecialSub missing"
In the event of a missing page, see if the "page name" could be understood as
"<literal><replaceable>product group</replaceable>/<replaceable>category</replaceable></literal>". If it could, use the provided information to construct
the search specification and invoke the search results page.
(More about &IC; search facilities can be read in <olink targetdoc='search'/>).
If it couldn't, return a &glos-false; value and proceed to display
"&conf-SpecialPage; <literal>missing</literal>".
</para><para>
Put the following in &ccf;:
<programlisting><![CDATA[
SpecialSub missing check_category
Sub check_category <<EOS
sub {
my ($name) = @_;
return unless $name =~ m{^[A-Z]};
$name =~ s,_, ,g;
my ($prod_group, $category) = split m{/}, $name;
$CGI->{co} = 1;
$CGI->{fi} = 'products';
$CGI->{st} = 'db';
$CGI->{sf} = join "\0", 'prod_group', 'category';
$CGI->{op} = join "\0", 'eq', 'eq';
$CGI->{se} = join "\0", $prod_group, $category;
$CGI->{sp} = 'results';
$CGI->{mv_todo} = 'search';
$Tag->update('process');
return (1, 'results');
}
EOS
]]></programlisting>
__END__
__NAME__ example: Defining SpecialSub init_session
If a client is coming from a "blacklisted" IP address, define
variable "blacklist" in its session.
</para><para>
At a later stage, "blacklisted" sessions could be prevented from
checking out and finalizing the order, as they are
likely to be fraudulent.
</para><para>
<programlisting><![CDATA[
SpecialSub init_session check_blacklist
Sub check_blacklist <<EOS
sub {
my ($session) = @_;
if ( grep { $CGI::remote_addr } @blacklisted_IPs ) {
$session->{blacklist} = 1;
}
return;
}
EOS
]]></programlisting>
__END__
__NAME__ example: Defining SpecialSub guess_cc_type
If the credit card number starts with "<literal>41</literal>",
recognize it as type "<literal>LOCAL_TYPE</literal>". Otherwise,
return a false value and implicitly instruct &IC; to continue with
the built-in credit card type detection mechanism.
</para><para>
Put the following in &ccf;:
<programlisting><![CDATA[
SpecialSub guess_cc_type check_cc
Sub check_cc <<EOS
sub {
my $num = shift;
return 'LOCAL_TYPE' if $num =~ /^41/;
return;
}
EOS
]]></programlisting>
__END__
__NAME__ example: Defining SpecialSub admin_init
Put the following in &ccf;:
<programlisting><![CDATA[
SpecialSub admin_init on_admin_init
Sub on_admin_init <<EOS
sub {
unless ($Session->{username} eq 'foundation') {
$Variable->{MV_MENU_DIRECTORY} = 'include/foundation/menus';
}
}
EOS
]]></programlisting>
__END__
__NAME__ example: Shipping discount for dealers with SpecialSub shipping_callout
<programlisting><![CDATA[
Sub custom_shipping <<EOS
sub {
my ($final, $mode, $opt, $o) = @_;
$final *= .90 if $Scratch->{dealer} and $mode =~ /UPS/i;
return $final;
}
EOS
SpecialSub shipping_callout custom_shipping
]]></programlisting>
__END__
__NAME__ example: Adjusting shipping weight with SpecialSub weight_callout
<programlisting><![CDATA[
Sub custom_weight <<EOS
sub {
my ($normal_weight) = @_;
my $new_weight = 0;
for my $item (@$Items) {
$new_weight += $item->{weight} * $item->{quantity}
unless $item->{is_free_shipping};
}
return $new_weight;
}
EOS
SpecialSub weight_callout custom_weight
]]></programlisting>
__END__
__NAME__ author
&mheins;
__END__