/
iccattut.xml
1253 lines (1154 loc) · 74.5 KB
/
iccattut.xml
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
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" standalone="no"?>
<!-- catalog not working ? -->
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook-Interchange XML V4.2//EN"
"../docbook/docbookxi.dtd">
<article id='iccattut'>
<articleinfo>
<title>Interchange Guides: the Catalog Building Tutorial</title>
<titleabbrev>iccattut</titleabbrev>
<copyright>
<year>2003</year><year>2004</year><year>2005</year>
<holder>Interchange Development Group</holder>
</copyright>
<copyright>
<year>2002</year>
<holder>Red Hat, Inc.</holder>
</copyright>
<authorgroup>
<author>
<firstname>Davor</firstname><surname>Ocelic</surname>
<email>docelic@icdevgroup.org</email>
</author>
<author>
<firstname>Jon</firstname><surname>Jensen</surname>
<email>jon@endpoint.com</email>
</author>
<author><firstname>Sonny</firstname><surname>Cook</surname>
<email>sonny@endpoint.com</email>
</author>
</authorgroup>
<!--
<revhistory>
<revision>
<revnumber>0</revnumber>
<date>Oct 2000</date>
<authorinitials>Sonny Cook</authorinitials>
<revremark>First conceived and written</revremark>
</revision>
<revision>
<revnumber>1</revnumber>
<date>Dec 2000</date>
<authorinitials>Jon Jensen</authorinitials>
<revremark>Edited and expanded</revremark>
</revision>
<revision>
<revnumber>2</revnumber>
<date>Jan 2001</date>
<authorinitials>Alison Smith and David Adams</authorinitials>
<revremark>Proofreading and clarification</revremark>
</revision>
<revision>
<revnumber>2.0pre</revnumber>
<date>7 Jul 2004</date>
<authorinitials>Davor Ocelic</authorinitials>
<revremark>
New documentation system,
XML conversion,
proofreading and expansion,
download link for tutorial files.
more proofreading and expansion,
more proofreading and expansion,
....
</revremark>
</revision>
</revhistory>
-->
<legalnotice>
<para>
This documentation is free; you can redistribute it and/or modify
it under the terms of the &GNU; General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
</para>
<para>
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
</para>
</legalnotice>
<abstract>
<para>
The purpose of this document is to guide you through constructing a simple &IC; catalog <emphasis role='bold'>from scratch</emphasis>. The standard catalogs that ship with Interchange are quite complex since they are ready to be used for business and highlight many of the capabilities that Interchange offers. Those catalogs may not be the right places to start the journey if you're interested in learning the basic Interchange building blocks.
</para> <para>
Although this tutorial provides ready-to-use examples, please <emphasis role='bold'>think</emphasis>
about them (and ideally, retype them instead of copy-pasting to your test catalog).
</para>
</abstract>
</articleinfo>
<sect1 id='BeforeYouBegin'>
<title>Before You Begin</title>
<sect2 id='Introduction'>
<title>Introduction</title>
<para>
Welcome to the &IC; Catalog Building Tutorial. Interchange originally started as an electronic cart and database display system, but over time it developed into a general application server. Interchange
is written in Perl programming language, and it gives you the full power of Perl in Interchange pages.
While being familiar with Perl (or programming languages in general) is definitely an advantage,
you do not have to be a programmer to use Interchange. Interchange offers elegant and
convenient, &glos-HTML;-like, &glos-ITL; (&IC; Tag Language) tags to
access its features.
</para> <para>
The simple Interchange &glos-catalog; you will create during this tutorial should give you a feel of the basic Interchange system. The catalog should also be considered a stepping stone to a more complete and functional Interchange-enabled website. We will rely on default settings as much as possible, to accentuate ideas instead of implementation. We will use a small number of Interchange features and still create a usable website (an on-line store in our example). <emphasis>The resulting site will be simple but usable</emphasis>. The value of this tutorial is in the explanations of the general Interchange ideas and small <emphasis>ready to use</emphasis> examples to get you up to speed.
</para> <para>
We recommend that you create the files used in this tutorial yourself. You will learn more by creating the directory structure and using your favorite text editor to create files in the proper places on your own system as they are discussed.
</para> <para>
Writing a complete tutorial without the feedback from the audience is hard. Please jot down your notes and remarks as you digest this tutorial and e-mail
authors with your comments.
</para>
</sect2>
<sect2 id='InterchangeandtheStandardDemoCatalogInstallation'>
<title>Interchange and the Standard Demo Catalog Installation</title>
<para>
For installation instructions, see
<olink targetdoc='install'/>.
</para>
</sect2>
<sect2 id='TestServerHostname'>
<title>Test Server Hostname</title>
<para>
We recommend that you always use your full system name (such as <systemitem class='systemname'>myhost.mydomain.local</systemitem>) instead of <systemitem class='systemname'>localhost</systemitem>. The HTTP State Management Mechanism (<ulink url="http://www.ietf.org/rfc/rfc2109.txt">RFC 2109</ulink>) specifies that cookies can only be set when the domain name contains at least two dots. Interchange does work even with client cookies disabled, but your session will be dropped every time you leave the catalog, since the session ID (which Interchange then embeds in the URL) will be lost.
</para> <para>
If your system does not have a suitable name, and you're not going to bother yourself with establishing one, there's the <filename>/etc/hosts</filename> file you can tune for the desired effect. Simply modify:
<programlisting>
127.0.0.1 localhost
</programlisting>
</para> <para>
to become
<programlisting>
127.0.0.1 localhost myhost.mydomain.local mydomain.local
</programlisting>
</para> <para>
and you'll be able to use <systemitem class='systemname'>myhost.mydomain.local</systemitem> as your server name.
</para>
</sect2>
<sect2 id='ImportantSettingsandPaths'>
<title>Important Settings and Paths</title>
<para>
In order to follow this tutorial, you will need to know the following values:
</para>
<itemizedlist>
<listitem><para>
Default Interchange username:
<itemizedlist>
<listitem><para>
<systemitem class='username'>interchange</systemitem> (Debian GNU and tarballs)
</para></listitem>
<listitem><para>
<systemitem class='username'>interch</systemitem> (Red Hat)
</para></listitem>
</itemizedlist>
</para></listitem>
<listitem><para>
Interchange software directory (<firstterm>ICROOT</firstterm>):
<itemizedlist>
<listitem><para>
<filename class='directory'>/usr/lib/interchange/</filename> (Debian GNU and Red Hat)
</para></listitem>
<listitem><para>
<filename class='directory'>/usr/local/interchange/</filename> (tarball)
</para></listitem>
</itemizedlist>
</para></listitem>
<listitem><para id="catdir">
Base Interchange catalogs directory:
<itemizedlist>
<listitem><para>
<filename class='directory'>/var/lib/interchange/catalogs/</filename>
(Debian GNU)
</para></listitem>
<listitem><para>
<filename class='directory'>/var/lib/interchange/</filename>
(RPM-based systems)
</para></listitem>
</itemizedlist>
</para></listitem>
<listitem><para>
Interchange <filename class='directory'>cgi-bin</filename> directory:
<itemizedlist>
<listitem><para>
<filename class='directory'>/usr/lib/cgi-bin/ic/</filename>
(Debian GNU)
</para></listitem>
<listitem><para>
<filename class='directory'>/var/www/cgi-bin/</filename>
(RPM-based systems)
</para></listitem>
<listitem><para>
<filename class='directory'>/usr/lib/cgi-bin/</filename>
(tarball)
</para></listitem>
</itemizedlist>
</para></listitem>
<listitem><para>
Standard demo catalog URL:
<itemizedlist>
<listitem><para>
<ulink url="http://myhost.mydomain.local/cgi-bin/ic/standard/index.html"/> (Debian GNU)
</para></listitem>
<listitem><para>
<ulink url="http://myhost.mydomain.local/cgi-bin/standard/index.html"/> (RPM-based systems and tarballs)
</para></listitem>
</itemizedlist>
</para></listitem>
</itemizedlist>
<important><para>
The Interchange installation routine is very flexible and the resulting file locations on your system may vary, depending on how your system was set up. We recommend that you do not proceed until you are sure you know the correct filesystem paths and have the necessary permissions to write them.
</para></important>
</sect2>
<sect2 id='InterchangeDaemonandCatalogs'>
<title>Interchange Daemon and Catalogs</title>
<para>
To control the Interchange daemon, use the <filename class='directory'>init.d</filename> script supplied with the RPM and DEB packages. For example, to start Interchange, run <userinput>/etc/init.d/interchange start</userinput> or <userinput>/etc/rc.d/init.d/interchange start</userinput>. To stop or restart Interchange, simply use <userinput>stop</userinput> or <userinput>restart</userinput> as arguments.
</para><para>
For more detailed information, see &howto-daemon-control;.
</para>
</sect2>
</sect1>
<sect1 id='MinimalCatalog'>
<title>Minimal Catalog</title>
<sect2 id='CatalogFiles'>
<title>Catalog Files</title>
<para>
This section describes the minimum of files and directories that need to be established to create a properly functioning catalog named "<firstterm>tutorial</firstterm>". Start creating the files with superuser privileges; you'll be notified when we move to regular users space.
</para>
</sect2>
<sect2 id='LinkProgram'>
<title>Link Program</title>
<para>
First of all, you need a &glos-link-program;. Read the &glos-link-program; glossary entry for an introduction and compilation instructions.
</para><para>
It is perfectly possible to re-use the existing link program. So if you
already have one (used by some other catalog <emphasis>from the same &IC;
server</emphasis>), you only need to find it (look into your <filename class='directory'>cgi-bin</filename> directory) and copy it to a new catalog's name,
making sure the permissions stay intact. Run
<itemizedlist>
<listitem><para>
<userinput>cd /usr/lib/cgi-bin/ic; cp -p vlink tutorial</userinput>
(on Debian GNU), or
</para></listitem>
<listitem><para>
<userinput>cd /var/www/cgi-bin; cp -p standard tutorial</userinput>
(on RPM-based systems).
</para></listitem>
</itemizedlist>
If everything is working correctly, typing <userinput>ls -l /usr/lib/cgi-bin/ic/</userinput> or <userinput>ls -l /var/www/cgi-bin</userinput> should roughly describe your files like this:
<screen>
-rwsr-xr-x 1 interchange interchange 7708 Dec 16 22:47 standard
-rwsr-xr-x 1 interchange interchange 7708 Dec 16 22:47 tlink
-rwsr-xr-x 1 interchange interchange 7708 Dec 16 22:47 tutorial
-rwsr-xr-x 1 interchange interchange 7708 Dec 16 22:47 vlink
</screen>
</para> <para>
The link program enables communication with the Interchange daemon. You might notice both <filename>vlink</filename> and <filename>tlink</filename> files present; the former uses Unix sockets to talk to the Interchange daemon (what you want most of the time), while the latter uses Inet sockets<footnote><para>Unix sockets are a way for programs on the same machine to communicate. It is not possible to connect to an Unix socket remotely (this is interprocess communication, mind you, and it doesn't mean you can't browse the website from a different machine). When you need remote connection, you then have to use Inet sockets.</para></footnote> and won't be used in this tutorial.
</para>
</sect2>
<sect2 id='CatalogRootDirectory'>
<title>Catalog Root Directory (CATROOT)</title>
<para>
In the <link linkend="catdir">Interchange (base) catalogs directory</link>, you need to create a new subdirectory for the tutorial catalog. This is where all of your catalog-specific files will go. The directory needs to be readable, writable, and executable by the Interchange user. This will be referred to as your <emphasis>catalog directory</emphasis><footnote><para>Please note the difference between <emphasis>Interchange catalogs directory</emphasis> which holds all of the catalogs, and the <emphasis>catalog directory</emphasis> which, always in a context, designates one of the subdirectories.</para></footnote> or &glos-CATROOT;. Type the following from the corresponding base catalogs directory on your system:
<programlisting>
mkdir tutorial
chown interchange.interchange tutorial
chmod 775 tutorial
</programlisting>
</para>
<para>
<emphasis role='bold'>For the rest of this tutorial, all file locations will be given relative to this tutorial catalog directory (&glos-CATROOT;). For example, <filename>pages/ord/basket.html</filename> would be <filename>/var/lib/interchange/catalogs/tutorial/pages/ord/basket.html</filename> on Debian GNU, <filename>/var/lib/interchange/tutorial/pages/ord/basket.html</filename> on RPM-based systems, or another equivalent on your system. The only exception is <filename>interchange.cfg</filename>, which is implicitly meant to be edited in <filename class='directory'>/etc/interchange/</filename> (or in the Interchange software directory &glos-ICROOT;, depending on the installation).</emphasis>
</para> <para>
<emphasis role='bold'>In addition, at places which require full pathnames (or other "hard-coded" values, such as usernames), Debian defaults will be used to avoid duplication and preserve the natural text flow. RPM-based systems users, please translate Debian GNU paths and other names to your system equivalents by following the rules from the <xref linkend="ImportantSettingsandPaths"/>. We think you have precise enough information that there should be no problem with this simple task.</emphasis>
</para>
</sect2>
<sect2 id='Interchange_managedCatalogSubdirectories'>
<title>Interchange-managed Catalog Subdirectories</title>
<para>
Now switch from the superuser to the Interchange user (<systemitem class='username'>interchange</systemitem> by default), by typing <userinput>su -s /bin/sh - interchange</userinput>. It is important to complete the rest of the steps under the "interchange" account or you'll run into permission problems later. (By the way, also make sure your <firstterm>umask</firstterm> setting is correct by running <userinput>umask 022</userinput>).
</para> <para>
Move to the catalog root directory (with the <userinput>cd /var/lib/interchange/catalogs/tutorial</userinput> or <userinput>cd /var/lib/interchange/tutorial</userinput> command).
</para> <para>
You need to create few catalog subdirectories that Interchange will use as it sees fit. The <filename class='directory'>session/</filename> subdirectory of the catalog root will be used to save information on visitors' browsing sessions. The <filename class='directory'>etc/</filename> and <filename class='directory'>tmp/</filename> directories are needed too, your catalog wouldn't work without them. The directories go under your catalog directory. Type <userinput>mkdir session etc tmp</userinput> to create them all.
</para>
<para>
For the next part, prepare your text editor of preference (vim, emacs, pico, joe, gedit, or nedit, to name a few).
</para>
</sect2>
<sect2 id='CatalogRegistration:interchange_cfg'>
<title>Catalog Registration: interchange.cfg</title>
<para>
Interchange configuration is controlled by a number of directives, which are specified in two main files. Global configuration directives go to the <filename>interchange.cfg</filename> file which is common for all catalogs running on servers started from the same Interchange installation directory (&glos-ICROOT;). Catalog-specific configuration directives go to <filename>catalog.cfg</filename> in the catalog directory (&glos-CATROOT;).
</para> <para>
The first directive we need to add is the global <option>Catalog</option> directive, specifying details for the new catalog. Open file <filename>/etc/interchange/catalogs.cfg</filename> and add the following:
<programlisting>
Catalog tutorial /var/lib/interchange/catalogs/tutorial /cgi-bin/ic/tutorial
</programlisting>
</para> <para>
At the end of <filename>/etc/interchange/interchange.cfg</filename>, add:
<programlisting>
DebugFile /var/log/interchange/debug.log
ErrorFile /var/log/interchange/error.log
</programlisting>
</para> <para>
As you can intuitively see, an example of a complete (although somewhat basic) configuration directive consists of the directive name (<literal>Catalog</literal>, <literal>DebugFile</literal>, <literal>ErrorFile</literal>, ...), followed by directive-specific parameters. Any number of spaces or tabs can appear between the directives and their options. The directives are case-insensitive, but it is recommended that you stick to your choice for readability. You can insert blank lines or comment lines (lines where the first non-blank character is '#') throughout the configuration files. The order in which the lines appear is important, but this won't matter in the simple catalog we're creating.
</para>
<para>
For more information on &IC; configuration files, see &glos-configuration;
glossary entry.
</para>
</sect2>
<sect2 id='CatalogConfiguration:Catalog_cfg'>
<title>Catalog Configuration: catalog.cfg</title>
<para>
There are few <filename>catalog.cfg</filename> directives that Interchange expects to see in order to complete the minimum configuration. Those directives are <option>VendURL</option> (your catalog's base URL), <option>SecureURL</option> (HTTPS base URL), <option>MailOrderTo</option>, <option>Database</option> and <option>ProductFiles</option>. If you do not have a suitable HTTPS location for your catalog (if you're not running https, for example), simply use the same value as for <option>VendURL</option>. In our catalog, we will use a minimal <database class='table'>products</database> table<footnote><para>Keep in mind that Interchange uses both terms "database" and "table" to identify the same thing - a table. This terminology is a historic leftover from the time when Interchange only used a single table.</para></footnote> with only the three necessary fields. The table will be TAB delimited text file, stored in <filename>products/products.txt</filename>. In general, you can specify unlimited number of databases of any type (for unlimited purposes), but at least one must be considered a <firstterm>Product Files</firstterm> database, reflecting Interchange's e-commerce roots.
</para> <para>
So the basic <filename>/var/lib/interchange/catalogs/tutorial/catalog.cfg</filename> config file should look like this:
</para> <para>
<programlisting>
<xi:include parse='text' href='../files/tutorial-phase1/catalog.cfg'/>
</programlisting>
</para>
</sect2>
<sect2 id='ProductsDatabase'>
<title>Products Database</title>
<para>
The <database class='table'>products</database> database we mentioned, kept in <filename>products/products.txt</filename>, will serve two purposes. It will provide Interchange with the layout of the products database table and it will also provide the data. When Interchange comes around to parse the <filename>products.txt</filename> file, it will expect the first line to contain the names of the fields for the database table (the <database class='field'>sku</database>, <database class='field'>description</database> and <database class='field'>price</database> fields are mandatory for a products database, but you can add arbitrary other fields as you see fit). The first field in the list is expected to be the primary key (unique identifier). In most cases you are going to use the &glos-SKU; (<firstterm>Stock Keeping Unit</firstterm>) as the unique identifier for each product. The simple store that we are going to build will sell some kind of tests or exams. You can choose another sample product line, but it is recommended that you keep it simple. Create the file <filename>products/products.txt</filename>, separating fields <emphasis>with a single TAB</emphasis>:
<programlisting>
<xi:include parse='text' href='../files/tutorial-phase1/products/products.txt'/>
</programlisting>
</para> <para>
You may notice that the columns don't line up in your text editor. This is the nature of tab-delimited files. Do not try to fix these.
</para> <para>
If you need more entries for the sample products database, you can use the <ulink url="files/dbgen">dbgen</ulink> Perl script to automatically create random database files for testing. The output of the script is much more meaningful if you provide it a list of words to work on (instead of just random characters) so make sure you have the <filename>/usr/share/dict/words</filename> file (in Debian, it's provided by the <literal>wenglish</literal> package), and then run <userinput>perl dbgen -c 10 -r /usr/share/dict/words > products/products.txt</userinput>. See the script source for available options and the complete usage syntax.
</para> <para>
It is important to know that Interchange does not use plain-text &glos-database;s (such as our <systemitem class='database'>products</systemitem> database) as-is; the performance would be poor. So instead, the data is imported and stored in a variant of the DBM database (Berkeley DB or GDBM, depending on which variant is available on your system —). That's why on most Linux systems, you will see the <filename>products/products.gdbm</filename> file created once you put the catalog on-line. It is also possible to specify a different backend, such as &MYSQL;, &PGSQL; or &ORACLE; database; in fact, most non-trivial setups choose some &glos-SQL; backend.
</para> <para>
To just briefly mention it, whenever you use a DBM-based backend and edit the text database file, Interchange will detect the change and re-import the source file into the DBM database on next access. All aspects of this auto-import (including its deactivation) are of course controlled by config file options (but are out of scope of this tutorial).
</para> <para>
Now that we have the majority of base files ready, we just need to create the HTML page templates.
</para>
</sect2>
</sect1>
<sect1 id='PageTemplates'>
<title>Page Templates</title>
<sect2 id='Organization'>
<title>Organization</title>
<para>
Since most sites have certain aspects of the site that remain the same as the content of the pages changes, we are going to create a template that we can use for all pages. We'll divide the page into four sections:
<literallayout>
<screen>
_____________________
| |
| top |
| |
|---------------------|
| | |
| | |
| left | main |
| | |
| | |
|---------------------|
| |
| bottom |
|_____________________|
</screen>
</literallayout>
</para> <para>
The <emphasis>main</emphasis> section will hold the content different for each page. The <emphasis>top</emphasis> section will be used for headers, banners, menus, and so on. The <emphasis>left</emphasis> section can be used as a sidebar or navigation bar, and the <emphasis>bottom</emphasis> section can contain the copyright and contact info. The top, left, and bottom sections will remain constant throughout the site. Making a change to information in one of these sections will make that change to all pages in your site.
</para> <para>
Now using the code displayed below, create the appropriate HTML files for each of the sections (naming the files after sections). No '.html' suffixes are needed here because those file parts are not meant to (and in fact can't) be parsed as standalone documents by Interchange (or the web server).
</para>
</sect2>
<sect2 id='CATROOT/top'>
<title>CATROOT/top</title>
<para>
<programlisting>
<xi:include parse='text' href='../files/tutorial-phase1/top'/>
</programlisting>
</para>
</sect2>
<sect2 id='CATROOT/left'>
<title>CATROOT/left</title>
<para>
<programlisting>
<xi:include parse='text' href='../files/tutorial-phase1/left'/>
</programlisting>
</para>
</sect2>
<sect2 id='CATROOT/bottom'>
<title>CATROOT/bottom</title>
<para>
<programlisting>
<xi:include parse='text' href='../files/tutorial-phase1/bottom'/>
</programlisting>
</para>
</sect2>
<sect2 id='ITL:theInterchangeTagLanguage'>
<title>ITL: the Interchange Tag Language</title>
<para>
We need a way to pull those template pieces we just created into the proper places to make complete, reviewable pages. This is done using &glos-ITL;, the Interchange Tag Language.
</para>
<tip>
<para>
ITL uses "tags" (enclosed in [tag] brackets), much like the &glos-HTML; uses tags enclosed in <tag>. The major difference, however, is in the hierarchy where the tags are parsed. ITL tags, parsed on the server side by the Interchange daemon, are expanded into the plain text and HTML which is then (over the web server) delivered to the end user and parsed there for final presentation in user's browser.
</para>
</tip>
<para>
ITL is at the heart of almost all Interchange catalog pages: ITL is the way you use Interchange's functionality. The ITL tags appear between square brackets, and accept <emphasis>all named</emphasis> or <emphasis>all positional</emphasis> parameters; here's an example (make sure you understand this!):
<programlisting>
[data table="products" column="price" key="1299"] (named parameters, <replaceable>NAME</replaceable>=<replaceable>VALUE</replaceable> <replaceable>NAME</replaceable>=<replaceable>VALUE</replaceable> ...)
[data products price 1299] (positional parameters, <replaceable>VALUE</replaceable> <replaceable>VALUE</replaceable> ...)
</programlisting>
</para>
<important><para>
You can't use positional parameters if the values contain whitespace. For example, <code>[tagname "[data session mv_arg]"]</code> is invalid; the only way to specify that is <code>[tagname optionname="[data session mv_arg]"]</code>. Also, if the first parameter is positional, all must be positional (and vice versa, if the first parameter is named — all must be named).
</para></important>
<para>
Tags can span multiple lines which helps readability when the tags have a large number of (long) options. There's a whole lot of tags available (around 200 in Interchange 5.2), but in this tutorial very few will be addressed. For a complete listing of the &glos-ITL; tags, see the <olink targetdoc='tags' targetptr='tags'>Tags</olink> reference.
</para> <para>
The first tag we'll use is going to be the <tag>include</tag> tag; it reads the specified file (relative to the catalog directory — &glos-CATROOT;), reparses it for any Interchange tags, and puts the final result in place of the tag. We'll demonstrate that now on the next page you'll need to create.
</para>
</sect2>
<sect2 id='WelcomePage'>
<title>Welcome Page</title>
<para>
Create a directory called <filename class='directory'>pages/</filename> in your tutorial catalog directory (the &glos-CATROOT;).
</para> <para>
Save the following text as <filename>pages/index.html</filename>. This will create a page to test that everything works so far.
<programlisting>
<xi:include parse='text' href='../files/tutorial-phase1/pages/index.html'/>
</programlisting>
</para> <para>
Interchange pages in the <filename class='directory'>pages/</filename> directory (or elsewhere, when configured) must have the .html suffix. You can omit the suffix in both your URLs when accessing pages with a Web browser, and in the tags you call (such as <tag>page</tag>), but the files on the disk must be properly named. (In fact, the actual suffix is controlled by the &conf-HTMLsuffix; config directive).
</para>
</sect2>
<sect2 id='TutorialCataloginAction'>
<title>Tutorial Catalog in Action</title>
<para>
As the superuser, first restart Interchange to make sure all changes are applied to the &IC; server and catalog.
</para> <para>
Monitor the log files: <userinput>tail -f /var/log/{interchange,apache*}/*log</userinput>
</para> <para>
Open the web browser and load the page. Your URL should be <ulink url="http://myhost.mydomain.local/cgi-bin/ic/tutorial/index.html"/> or <ulink url="http://myhost.mydomain.local/cgi-bin/tutorial/index.html"/>. Since the <filename>catalog.cfg</filename> only contains minimal configuration, <filename>index.html</filename> is not defined as the default page, so you can't leave it out of the URL.
</para> <para>
<emphasis role='bold'>Congratulations!</emphasis> Your basic, "phase 1" catalog is now hopefully finished and working ;)
</para>
</sect2>
<sect2 id='Phase1:TutorialFiles'>
<title>Phase 1: Tutorial Files</title>
<para>
We have prepared the files from this tutorial phase for download in
<ulink url="files/tutorial-phase1.tar">.tar</ulink>,
<ulink url="files/tutorial-phase1.tar.gz">.tar.gz</ulink>,
<ulink url="files/tutorial-phase1.tar.bz2">.tar.bz2</ulink>, and
<ulink url="files/tutorial-phase1/">expanded</ulink>
formats. Special notes on turning the files into a working catalog are not included; that's what this document is for.
</para>
</sect2>
</sect1>
<sect1 id='Troubleshooting'>
<title>Troubleshooting</title>
<sect2 id='TroubleshootingChecklist'>
<title>Troubleshooting Checklist</title>
<para>
Your first Interchange page should have displayed in your browser as we described. If it didn't, you need to figure out what went wrong. Most of the time, overlooked details are the problem. Double-checking your typing is a good habit to get into.
</para> <para>
Here's also the troubleshooting checklist to use when you run into problems:
</para>
<itemizedlist>
<listitem><para>
Have you created directories with the proper names in the proper locations?
</para></listitem>
<listitem><para>
Have you misspelled any file names or put them in the wrong directories? Are the files and parent directories readable by the interchange user? Double-check with the <command>ls</command> command.
</para></listitem>
<listitem><para>
Did you type letters in the proper case? Remember that both Unix and Interchange are case-sensitive, and for the most part you may not switch upper- and lower-case letters.
</para></listitem>
<listitem><para>
Did you type all punctuation, ITL tags, and HTML tags correctly?
</para></listitem>
<!--
<listitem><para>
Did you use whitespace correctly in the cases where it mattered? Remember to use tabs when tabs are called for (in lists and database text files).
</para></listitem>
-->
<listitem><para>
Did you restart Interchange if you changed anything in <filename>interchange.cfg</filename> or <filename>catalog.cfg</filename>, or if you're in a high-traffic mode?
</para></listitem>
<listitem><para>
Check your catalog error log, error.log in your tutorial catalog directory, to see if Interchange reported any errors.
</para></listitem>
<listitem><para>
Check the Interchange server error log, error.log in the Interchange software directory, to see if it had problems configuring the catalog in the first place.
</para></listitem>
<listitem><para>
View the HTML source of any catalog pages that are loading incorrectly to check for a coding error. The problem may reveal itself when you see what HTML the browser is getting.
</para></listitem>
</itemizedlist>
</sect2>
<sect2 id='MonitoringLogFiles'>
<title>Monitoring Log Files</title>
<para>
The key pseudo-troubleshooting technique that solves 99% of the problems with minimal effort is <emphasis role='bold'>log file monitoring</emphasis>. Before proceeding, open up a new terminal and run the following (with root privileges): <userinput>tail -f /var/log/{apache*,interchange}/*log</userinput>.
</para> <para>
Once you have the logs monitored, restart Interchange and visit the catalog's index.html. Any problems should be reported in the logs.
</para>
</sect2>
</sect1>
<sect1 id='ProductDisplay'>
<title>Product Display</title>
<sect2 id='ProductListing'>
<title>Product Listing</title>
<para>
Now that your sample catalog is up and running, we'll display your products on the welcome page. We will loop over all of the products in our database and produce an entry for each product in the table. Replace the line "This is where your content goes" line in <filename>pages/index.html</filename> with the following:
<programlisting><![CDATA[
<table cellpadding="5">
<tr>
<th>Test #</th>
<th>Description</th>
<th>Price</th>
</tr>
. . .
</table>
]]></programlisting>
</para> <para>
Now we will use Interchange tags to fill in the rest of the table with the products database you created. The <tag>loop</tag> ITL tag pair tells Interchange to iterate over each item in the parameter list. In this case, the loop runs over the results of an Interchange search. The search parameter does a database search on the provided parameters. In this case, <emphasis role='bold'>we're doing a very simple search that returns all of the fields for all of the entries in the <database class='table'>products</database> database</emphasis>. The parameters passed to the search tell Interchange to return all records ('ra') from the products file ('fi'). The following should take the place of the ellipsis (the "three dots") in the above code that we placed in <filename>pages/index.html</filename>:
<programlisting><![CDATA[
[loop search="ra=yes/fi=products"]
. . .
[/loop]
]]></programlisting>
</para> <para>
In the loop we just established, the individual elements of each record are accessed using the <tag>loop-field</tag> tag. The following code should replace the above ellipsis in the code we placed in <filename>pages/index.html</filename>:
<programlisting><![CDATA[
<tr>
<td>[loop-code]</td>
<td>[loop-field description]</td>
<td align="right">[loop-field price]</td>
</tr>
]]></programlisting>
</para> <para>
The <code>[loop-code]</code> tag refers to the primary key (unique identifier) for the current row of the database table in question. In this case, it will produce the same output as the <code>[loop-field sku]</code> tag, because the 'sku' field is the primary key ("code") for products table. In each case, the tag is replaced by the appropriate element. When put together, Interchange generates a page with your products table on it.
</para> <para>
Your finished <filename>pages/index.html</filename> page should look like this:
<programlisting>
<xi:include parse='text' href='../files/tutorial-phase2/pages/index.html'/>
</programlisting>
</para> <para>
Test it by refreshing <filename>index.html</filename> page in your browser.
</para>
</sect2>
<sect2 id='pages_flypage'>
<title>pages/flypage.html</title>
<para>
The next step is to create an individual page for each item. You could theoretically create each page manually, but that approach isn't worth considering. So to do this the right way, we need to create a <emphasis>special generic page</emphasis> called <firstterm>the flypage</firstterm> (<filename>pages/flypage.html</filename>). When a page is requested that does not exist in the <filename class='directory'>pages/</filename> directory, Interchange will check and see if the requested page is equal to an existing product code from the <database>products</database> database table. If it does, it will then show the flypage and populate it with the corresponding product's data. If there's no product with that ID, the special error page <filename>special_pages/missing.html</filename> (described in the next section) will be displayed.
</para> <para>
For example, if you request page <filename>0198.html</filename>, Interchange first checks if that specific page exists (<filename class='directory'>pages/0198.html</filename>). If one is not found, it searches the products database table for product code <literal>0198</literal>. When found, Interchange creates product page <emphasis>on the fly</emphasis> using <filename>pages/flypage.html</filename>. When constructing the flypage, the entire product record for the requested product is available through the <tag>item-field</tag> tag (similar to the <tag>loop-field</tag> tag). To create a fly page, type the following code and save it as <filename>pages/flypage.html</filename>.
<programlisting>
<xi:include parse='text' href='../files/tutorial-phase2/pages/flypage.html'/>
</programlisting>
</para>
</sect2>
<sect2 id='special_pages_missing'>
<title>special_pages/missing.html</title>
<para>
Create the <filename class='directory'>special_pages/</filename> directory in your catalog directory (the &glos-CATROOT;).
</para> <para>
It is a good idea to display an error page when Interchange is asked for an unknown page. To create a missing page for display, type the following and save it as <filename>special_pages/missing.html</filename>.
<programlisting>
<xi:include parse='text' href='../files/tutorial-phase2/special_pages/missing.html'/>
</programlisting>
</para> <para>
The addition of this page ensures that users see your error message instead of a mysterious server error if they mistype the URL or click a broken link.
</para>
</sect2>
<sect2 id='Phase2:TutorialFiles'>
<title>Phase 2: Tutorial Files</title>
<para>
We have prepared the files from this tutorial phase for download in
<ulink url="files/tutorial-phase2.tar">.tar</ulink>,
<ulink url="files/tutorial-phase2.tar.gz">.tar.gz</ulink>,
<ulink url="files/tutorial-phase2.tar.bz2">.tar.bz2</ulink>, and
<ulink url="files/tutorial-phase2/">expanded</ulink>
formats.
</para>
</sect2>
</sect1>
<sect1 id='TheShoppingBasket'>
<title>The Shopping Basket</title>
<sect2 id='OrderLink'>
<title>Order Link</title>
<para>
Now that you have your products available, let's add a shopping cart so customers can purchase them. This is simply created using the <tag>order</tag> tag. The tag creates an HTML link that causes the specified item to be ordered and takes the shopper to her basket page. This is a built-in shortcut to the complete order process which uses an HTML form submission process. The parameter for the <tag>order</tag> tag is the product ID. To add these tags to the catalog, make the following change to <filename>pages/index.html</filename>:
<programlisting><![CDATA[
[loop-field description]
</a>
</td>
<td align="right">[loop-field price]</td>
+ <td>[order [loop-code]]Order Now</a></td>
</tr>
[/loop]
]]></programlisting>
</para> <para>
The single line you need to add is marked by a '+'. However, do not include the '+' when adding this line. The surrounding lines are shown to give you the context. This style is called "context diff", and will be used extensively.
</para>
</sect2>
<sect2 id='pages_ord_basket'>
<title>pages/ord/basket.html</title>
<para>
Create the directory <filename class='directory'>pages/ord/</filename> in the tutorial catalog directory.
</para> <para>
For the <tag>order</tag> tag, Interchange expects a default page called <filename>pages/ord/basket.html</filename>. This page displays the contents of the shopping basket and contains other shopping basket functionality.
</para> <para>
The standard demo catalog has a full-featured shopping basket available for use, but this tutorial teaches you to build your own simple one. The shopping basket items can be accessed using a set of tags that have prefix of "item". Put the following code in the new <filename>pages/ord/basket.html</filename> file. The section that follows explains the tags used.
<programlisting>
<xi:include parse='text' href='../files/tutorial-phase3/pages/ord/basket.html'/>
</programlisting>
</para> <para>
The basket items can be accessed one at a time by using the <tag>item-list</tag> tag. So we will create a table by iterating through the basket items. The text within the <tag>item-list</tag> <tag>/item-list</tag> tags is created for each item in the list.
</para> <para>
<code>[item-quantity]</code> shows the quantity of the item ordered. If the same item is ordered multiple times, the quantity increases.
</para> <para>
<code>[item-field description]</code> shows the description from the product database table. Any field that is not special to Interchange can be accessed from the shopping cart this way.
</para> <para>
<tag>item-price</tag> shows the per-item price that is defined in the product database table.
</para> <para>
<tag>item-subtotal</tag> shows the total cost of this order line. This is normally the price multiplied by the quantity, but it can also take into account other considerations, such as various kinds of price discounts.
</para> <para>
<tag>subtotal</tag> shows the calculated shopping basket subtotal.
</para> <para>
<code>[page index]</code> creates the starting HTML <a href=...> for a link to the catalog welcome page.
</para> <para>
You also need to put a link in the index page so that shoppers can go to their shopping cart without ordering something. Modify the end of <filename>pages/index.html</filename> by adding the following lines:
<programlisting><![CDATA[
</table>
+ <hr>
+ <p align=center>[page order]View shopping cart</a></p>
[include bottom]
]]></programlisting>
</para> <para>
Refresh the index page and test the shopping basket in your browser.
</para>
</sect2>
<sect2 id='Phase3:TutorialFiles'>
<title>Phase 3: Tutorial Files</title>
<para>
We have prepared the files from this tutorial phase for download in
<ulink url="files/tutorial-phase3.tar">.tar</ulink>,
<ulink url="files/tutorial-phase3.tar.gz">.tar.gz</ulink>,
<ulink url="files/tutorial-phase3.tar.bz2">.tar.bz2</ulink>, and
<ulink url="files/tutorial-phase3/">expanded</ulink>
formats.
</para>
</sect2>
</sect1>
<sect1 id='OrderCheckout'>
<title>Order Checkout</title>
<sect2 id='pages_checkout'>
<title>pages/checkout.html</title>
<para>
The site can now be completed by adding the ability to check out with the shopping cart and finalize the order. To do this the customer needs to provide a shipping address (which, for the sake of this tutorial, we will assume is the same as the billing address), and payment information. We will process the order by verifying the customer's payment information and sending an email to the merchant (ourselves) detailing the order.
</para> <para>
We first need to create a checkout page. The checkout page consists of a form that receives order information from the customer and performs a simple credit card number check. In this tutorial we will use a built-in test that only checks to see if a given credit card number <emphasis>could</emphasis> be valid. If the information is acceptable the customer will move to the next phase of the order process. If it is not, an error page will be displayed.
</para> <para>
To create a checkout page, type the following code and save it as <filename>pages/checkout.html</filename>. The section that follows explains the code.
<programlisting>
<xi:include parse='text' href='../files/tutorial-phase4/pages/checkout.html'/>
</programlisting>
</para> <para>
The HTML form begins with a method of 'post' (which sends the form data as its own stream, as opposed to the 'get' method which encodes the data as part of the URL). The <tag>process</tag> tag creates a special URL for form processing. Interchange has a built-in form processor that is configured by submitting certain fields in the form. The Finalize button will invoke this form processor and link the user to the <filename>special_pages/receipt.html</filename> page, which is described later.
</para> <para>
The code <code>[form-session-id]</code> basically just expands to a
hidden form variable that specifies the &glos-session; ID. It is
<emphasis role='bold'>very important</emphasis> to always include
this in every &glos-HTML; form. That way, &IC; can work properly
<emphasis>even when the client is not accepting cookies!</emphasis>
</para> <para>
You are also submitting some hidden form values that will tell Interchange how to process this form. The first value, <mv>mv_todo</mv> was set to "<literal>submit</literal>". This causes the form to be submitted for validation. The second value, <mv>mv_order_profile</mv> was set to "<literal>order_profile</literal>. This determines the name of the profile according to which the validation will be performed.
</para> <para>
The last value, <mv>mv_cyber_mode</mv>, was set to "<literal>minivend_test</literal>". The <mv>mv_cyber_mode</mv> value determines what method will be used to charge a credit card. The value of <literal>minivend_test</literal> uses the internal test method, which calculates a simple checksum against the card to determine if it is a valid number.
</para> <para>
When preparing an order for processing, Interchange looks for certain named fields in the form to obtain name, address, and credit card information. We are using all expected (default) field names in this form so that no translation needs to take place.
</para> <para>
View the checkout page in your browser. The "Finalize!" link has not been enabled, but the page should display properly.
</para>
</sect2>
<sect2 id='etc_profiles_order'>
<title>etc/profiles.order</title>
<para>
You need to set up verification for the order form by defining an order profile for the form. An order profile determines what fields are necessary for the form to be accepted. Create an order profile by typing the following and saving it as <filename>etc/profiles.order</filename>. The section that follows explains the code used:
<programlisting>
<xi:include parse='text' href='../files/tutorial-phase4/etc/profiles.order'/>
</programlisting>
</para> <para>
A single file can contain multiple profile definitions. First the profile is named using the <pragma>__NAME__</pragma> pragma (but this is unrelated to the <varname>__<replaceable>VARIABLE</replaceable>__</varname> syntax seen elsewhere in Interchange). Then in the profile there is a list of the form fields that are required. The &fatal setting indicates that validation will fail if any of the requirements are not met. &final indicates that this form will complete the ordering process. This setting is helpful if you have a multi-page ordering process and you want to validate each page individually. The <pragma>__END__</pragma> pragma signals the end of this profile, after which you can begin another one.
</para> <para>
In order to activate your order profile, add the <option>OrderProfile</option> directive to the <filename>catalog.cfg</filename>:
<programlisting>
OrderProfile etc/profiles.order
</programlisting>
</para> <para>
Watch for white space in front of the <pragma>__NAME__</pragma> pragma, it can cause your profile to be ignored. Remember to reconfigure the catalog or simply restart Interchange altogether after modifying <filename>catalog.cfg</filename> or the profiles.
</para>
</sect2>
<sect2 id='special_pages_needfield'>
<title>special_pages/needfield.html</title>
<para>
If the submitted form lacks a required field, Interchange will display an error page. The default location is <filename>special_pages/needfield.html</filename>. Here's the code for the page:
<programlisting>
<xi:include parse='text' href='../files/tutorial-phase4/special_pages/needfield.html'/>
</programlisting>
</para> <para>
The <tag>error</tag> tag is the most important tag on this page. The 'all' parameter tells the tag to iterate through all of the errors reported from the failed verification, and the 'show_var' parameter indicates that the failed variable name should be displayed. For example, if the first name was left empty, 'fname' would be shown. The 'show_error' parameter displays the actual error for the variable. The joiner parameter inserts an HTML <br> tag between each error message, so each error is displayed on its own line. In more complex configurations, the <tag>error</tag> tag can be even more expressive.
</para>
</sect2>
<sect2 id='CreditCardProcessing'>
<title>Credit Card Processing</title>
<para>
This tutorial uses a very simple order process. To accomplish this, one more directive needs to be added to the file <filename>etc/profiles.order</filename>:
<programlisting><![CDATA[
&fatal=yes
&final=yes
+ &credit_card=standard keep
__END__
]]></programlisting>
</para> <para>
This issues two instructions to the credit card system.
</para> <para>
The first option, standard, uses the standard built-in encryption algorithm to encrypt the credit card number and erases the unencrypted copy from memory. We are using the standard option not to encrypt the number but to run the checksum verification on the number to verify that it is a potentially correct number. We will not be checking with a real payment processor to see if it actually is a valid card number. For testing purposes, you can use the card number 4111 1111 1111 1111, which will pass the checksum test.
</para> <para>
The second option, keep, keeps the credit card number from getting removed from memory. We want to keep the number in memory so that it is available when it is mailed as part of the order.
</para> <para>
If the credit card number passes and all of the required fields are present, the customer will be sent to the final page. Interchange then sends an e-mail to the store owner (you).
</para>
</sect2>
<sect2 id='etc_report'>
<title>etc/report</title>
<para>
When the customer's involvement in the order is complete, Interchange composes an email and sends it to the recipient defined in the <option>MailOrderTo</option> directive in <filename>catalog.cfg</filename>. The default location for this email report template is <filename>etc/report</filename>. Interchange tags can be used to fill in the body of the message.
</para> <para>
The report should include at least the customer's name, address, and the items they ordered. The following is a simple report template; save it as <filename>etc/report</filename>:
<programlisting>
<xi:include parse='text' href='../files/tutorial-phase4/etc/report'/>
</programlisting>
</para> <para>
This file is in plain text format where, unlike HTML, white space is relevant. It is fairly straightforward, except that the <tag>if</tag> tag was added to only include the optional second address line if the customer filled it in.
</para> <para>
One of the special properties of the <mv>mv_credit_card_number</mv> field is that Interchange specifically precludes the credit card number from being saved. This makes it unavailable to you in the <tag>value</tag> tag. The <tag>cgi</tag> tag is used to circumvent this important security measure in order to get the value submitted from the last form.
</para>
<warning><para>
Obviously it is a bad idea to send a real credit card number over an insecure channel like email. In a real configuration, you would encrypt the number securely before emailing or storing it.
</para></warning>
</sect2>
<sect2 id='special_pages_receipt'>
<title>special_pages/receipt.html</title>
<para>
Once the report has been run, Interchange will finish the order process on the customer side by displaying a success screen containing a receipt. The default location for this page is <filename>special_pages/receipt.html</filename>. To create a receipt page, type the following code and save it as <filename>special_pages/receipt.html</filename>.
<programlisting>
<xi:include parse='text' href='../files/tutorial-phase4/special_pages/receipt.html'/>
</programlisting>
</para> <para>
Once the order is processed, the customer's shopping cart is emptied.
</para> <para>
At this point you have a more-or-less functional store. Congratulations once again ;)
</para>
</sect2>
<sect2 id='Phase4:TutorialFiles'>
<title>Phase 4: Tutorial Files</title>
<para>
We have prepared the files from this tutorial phase for download in
<ulink url="files/tutorial-phase4.tar">.tar</ulink>,
<ulink url="files/tutorial-phase4.tar.gz">.tar.gz</ulink>,
<ulink url="files/tutorial-phase4.tar.bz2">.tar.bz2</ulink>, and
<ulink url="files/tutorial-phase4/">expanded</ulink>
formats.
</para>
</sect2>
</sect1>
<sect1 id='EnhancingtheCatalog'>
<title>Enhancing the Catalog</title>
<sect2 id='BasicEnhancements'>
<title>Basic Enhancements</title>
<para>
Now that you have a working catalog, you can go back and add improvements and test them incrementally. This section walks you through several, and then suggests even more enhancements you can attempt to do on your own (the <emphasis>exercises for the readers</emphasis> are fantastic, aren't they :).
</para>
</sect2>
<sect2 id='PricePictures'>
<title>Price Pictures</title>
<para>
You may have noticed that the product prices aren't formatted as prices usually are. The way to correct this is with an Interchange feature called <firstterm>price pictures</firstterm>.
</para> <para>
There are several properties to price pictures: the currency symbol, the thousands separator, the decimal point, the number of digits to show behind the decimal, and so on. Most Unix systems have U.S. currency and the English language as the default locale, which is called en_US. The only thing you need to do on such a system is specify the currency symbol, which, in this case, is the dollar sign. To do this, add the following line to your <filename>catalog.cfg</filename> file:
</para> <para>
<programlisting>
Locale en_US currency_symbol $
</programlisting>
</para> <para>
Restart Interchange and view your catalog. You will notice little has changed on the welcome page or the flypages, <emphasis role='bold'>but in the shopping cart</emphasis> (<filename>pages/ord/basket.html</filename>) all your prices should be formatted as U.S. dollars ("1347.3" has become "$1,347.30"). Why the currency is only displayed on the basket page is easy to understand; we use the <tag>item-price</tag> tag there. That tag is equivalent to <code>[item-field price]</code> used elsewhere, but it has that extra logic associated with it that automatically displays the currency format. To use <tag>item-price</tag> without the auto-format, you'd have to change the <code>[item-price]</code> tag to <code>[item-price noformat]</code>.
</para> <para>
But that's probably not what you want to do. You're probably more interested in formatting all the other prices (such as those on the Welcome page) to a proper currency-dependent display. To do that, you could obviously replace <code>[item-field price]</code> with <code>[item-price]</code>, but we'll take on more general approach here. Simply use the &tag-currency; tag for all price values. Make the following change to <filename>pages/index.html</filename>:
<programlisting><![CDATA[
[loop search="ra=yes/fi=products"]
<tr>
<td>[loop-code]</td>
<td>
<a href="[loop-code].html">
[loop-field description]
</a>
</td>
- <td align="right">[loop-field price]</td>
+ <td align="right">[currency][loop-field price][/currency]</td>
<td>[order [loop-code]]Order Now</a></td>
</tr>
[/loop]
]]></programlisting>
</para>
<note><para>
The line that begins with '-' should be deleted. Do not type the '-'. The next line, that starts with '+', replaces it. (It's the <emphasis>context diff</emphasis> format we mentioned, remember?)
</para></note>
<para>
A similar change to the <code>[item-field price]</code> tag in the <filename>pages/flypage.html</filename> page will fix that currency display. View the page in your browser. All your prices should be formatted for U.S. currency.
</para> <para>
If your prices are not being formatted correctly, your default system locale may be set up differently or your en_US locale settings may be wrong. There are a few other <filename>catalog.cfg</filename> directives you can use to correct the situation:
<programlisting>
Locale en_US p_cs_precedes 1
</programlisting>
Makes the currency symbol precede the currency value. A '0' setting makes the symbol come after the currency value.
</para> <para>
<programlisting>
Locale en_US mon_thousands_sep ,
</programlisting>
Sets your thousands separator to a comma. It can be set to any value.
</para> <para>
<programlisting>
Locale en_US mon_decimal_point .
</programlisting>
Sets your decimal separator to a comma. Many countries use a comma instead of a period to separate the integer from the decimal part.
</para>
<note><para>
Consult the Interchange documentation and your operating system manual for more information on locale settings.
</para></note>
</sect2>
<sect2 id='CatalogVariables'>
<title>Catalog Variables</title>
<para>
Interchange provides a very useful feature that has not been discussed yet called <firstterm>catalog variables</firstterm>. It provides a way for you to set a variable to a certain value in the <filename>catalog.cfg</filename> file and then use it anywhere in your catalog pages. The <option>Variable</option> directive allows an Interchange catalog variable to be created with the name coming from the first parameter and the value from the rest of the line, like this:
<programlisting>
Variable <replaceable>SOMENAME</replaceable> whatever value you want
</programlisting>
</para> <para>
To access that variable in your pages, type the token <varname>__<replaceable>SOMENAME</replaceable>__</varname>. Notice that there are two underscore characters before the variable name and two after it, and that in place of the word <replaceable>SOMENAME</replaceable> you would put the actual name of the variable. The first thing Interchange does on a page is to replace the token with the variable's value. The variable value can also include Interchange tags to be parsed.
</para> <para>
This was an example of a <emphasis>catalog</emphasis> variable. There are also <emphasis>global</emphasis> variables which are defined in the same way (but in the <filename>interchange.cfg</filename> file), and are accessed using the <varname>@@<replaceable>SOMENAME</replaceable>@@</varname> token. A convenient, <varname>@_<replaceable>SOMENAME</replaceable>_@</varname> syntax is also valid, and first checks the existence of a variable in the local catalog, falling back to the global value if no catalog-specific value has been set.
</para>
</sect2>
<sect2 id='MoreInterestingPageFooter'>
<title>More Interesting Page Footer</title>
<para>
You can put a contact email address at the bottom of each page in case your customers want to contact you. You could just add it to the footer, but by putting it into a variable you can use it in contact pages as well. This allows you to easily change the variable information and have that change reflected in all instances of that variable. The following is an example of how to set a catalog variable in <filename>catalog.cfg</filename>:
<programlisting>
Variable CONTACT_EMAIL myname.surname@mydomain.local
</programlisting>
</para> <para>
Now make the following change to your template file bottom:
<programlisting><![CDATA[
</td>
</tr>
<tr><td colspan="2" align="center">
- (bottom)
+ <a href="mailto:__CONTACT_EMAIL__">Contact us</a> if you have any questions.
</td>
</tr>
</table>
</div>
</body>
</html>
]]></programlisting>
</para> <para>
Be sure to restart Interchange (or reconfig the catalog at least) before reloading the page in your browser, since you made a change to <filename>catalog.cfg</filename>.
</para> <para>
Let's add another variable to your catalog. This variable demonstrates how an Interchange tag can be included in the variable. This Interchange tag returns the current date in a standard format. Add the following to <filename>catalog.cfg</filename>:
<programlisting>
Variable DISPLAYDATE [time]%A, %B %d, %Y[/time]
</programlisting>
</para> <para>
Now add the following to the left template piece:
<programlisting><![CDATA[
<tr>
<td align="center">
- (left)
+ __DISPLAYDATE__
</td>
<td align="center">
]]></programlisting>
</para> <para>
Restart Interchange and view the page.
</para>
</sect2>
<sect2 id='AdvancedCreditCardExpirationDateOptions'>
<title>Advanced Credit Card Expiration Date Options</title>
<para>
To reduce the possibility of human error at checkout time, most on-line stores use a pull-down option menu to list the months and the years for the credit card expiration date, instead of having the user to type the numbers by hand. The menu also lets you avoid explaining whether the user should enter a 2- or 4-digit year.
<!-- TODO: discuss security here -->
</para> <para>
Make the following change to your <filename>pages/checkout.html</filename> page. The section that follows explains the code. <emphasis role='bold'>Read the explanation section below before typing the code to be sure you know where tabs should be used instead of spaces and where to watch out for `back-ticks`</emphasis>.
<programlisting><![CDATA[
<tr>
<td align=right><b>Credit card expiration date:</b></td>
<td>
- Month (number from 1-12):
- <input type=text name=mv_credit_card_exp_month value="" size=2 maxlength=2>
- <br>
- Year (last two digits only):
- <input type=text name=mv_credit_card_exp_year value="" size=2 maxlength=2>