-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathiccattut.sdf
1151 lines (815 loc) · 58.7 KB
/
iccattut.sdf
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
!init OPT_LOOK="icdevgroup"; OPT_STYLE="manual"
# $Id: iccattut.sdf,v 1.22 2004-05-05 15:22:30 jon Exp $
!define DOC_NAME "Catalog-Building Tutorial"
!define DOC_TYPE ""
!define DOC_CODE "iccattut"
!define DOC_VERSION substr('$Revision: 1.22 $', 11, -2)
!define DOC_STATUS "Draft"
!define DOC_PROJECT "Interchange"
!define DOC_URL "http://www.icdevgroup.org/doc/iccattut.html"
!define DOC_OWNER "Copyright 2002-2004 Interchange Development Group. Copyright 2000-2002 Red Hat, Inc."
!build_title
H1:Purpose
N:The purpose of this document is to guide you through constructing a simple Interchange catalog from scratch. The demo catalog that ships with Interchange is quite complex since it highlights some of the many capabilities that Interchange offers. As a template for your own catalog, the demo can be an intimidating place to start if your purpose is to learn.
The simple catalog you create using this tutorial should give you a feel for the basic Interchange system. It should also be considered a stepping stone to a more complete and functional e-commerce system built with Interchange. The tutorial relies as much as possible on default settings to accentuate how Interchange works. It will use as few of Interchange's capabilities as possible, while still building a usable store. The resulting site will be simple but usable. The value of this tutorial is in the instruction that occurs along the way.
It is recommended 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.
H1:Before you begin
N:This section explains the initial set up tasks that must be completed before you can begin building your simple e-commerce site.
H2:Install Interchange and the demo catalog
N:The easiest way to get Interchange and the demo set up is through an {{1:RPM install}} on the Red Hat Linux or Linux Mandrake operating systems. You can also get Interchange by unpacking an Interchange tarball or checking out a copy of the CVS repository and doing a {{1:manual installation}}. These installations can be done either as a regular user or as root, installing for a special Interchange user.
You must also know what type of installation you ran so you know where to place the various files created. Before proceeding, verify that Interchange is properly installed. Also, keep in mind which type of installation you did:
*RPM (RPM Package Manager) install
*Manual install as root
*Manual install as regular user
Note:After installation, {{FILE:makecat}} should be run to build your catalog. For information on installing Interchange and building your catalog using {{FILE:makecat}}, see the {{1:Interchange Getting Started Guide}}. Do not to continue with this tutorial without a working demo catalog.
N:Installing the demo catalog set up the Interchange global configuration file {{FILE:interchange.cfg}}, which resides in the Interchange software directory. Also, it compiled the link program for your specific server and placed the executable program in your cgi-bin directory. This is necessary for your catalog to run properly.
H2:The Interchange operating system user
N:If Interchange was installed as a regular user, that will be the user Interchange runs as. If Interchange was installed as root or from an RPM, you need to know the name of the separate Interchange user. The Interchange daemon will not run as root, and should not run as the web server user (usually 'apache', 'www', 'httpd', or 'nobody'). If Interchange was installed from the RPM, or with the default source installation settings, the username is {{EX:interch}}. If you selected a different user name, you will need to know what it is.
H2:Important directories
N:In order to complete this tutorial you will need to know the location of each of the following directories and have write permissions on them:
*Interchange software directory
**{{B:RPM install:}} /usr/lib/interchange
**{{B:Manual install as root:}} /usr/local/interchange
**{{B:Manual install as regular user:}} /home/username/interchange
*Catalogs directory
**{{B:RPM install:}} /var/lib/interchange
**{{B:Manual install as root:}} /usr/local/interchange/catalogs
**{{B:Manual install as regular user:}} /home/username/catalogs
*cgi-bin directory
**{{B:RPM install or source install as root:}} /var/www/cgi-bin
**{{B:Manual install as root (locally installed web server):}} /usr/local/htdocs, /opt/www, ...
**{{B:Manual install as regular user:}} /home/username/public_html (with .cgi extension)
Note:The installation of Interchange is very flexible and the file locations on your system may vary, depending on how your system was set up. It is recommended that you not proceed until you are sure you have this information and the necessary permissions to write to these directories.
H2:Your catalog URL
N:Finally, you need to know the URL to access your store from a web browser. Again, this can vary depending on how your web server has been set up. But, assuming a common setup of the Apache web server, your URL should be one of the following:
*{{B:Root or RPM install:}} {{EX:http://localhost/cgi-bin/tutorial/pagename}}
*{{B:Manual install as user:}} {{EX:http://localhost/~username/tutorial.cgi/pagename}}
N:If you aren't running your web browser on the server where Interchange is running, you need to substitute your server's host name (for example: {{EX:machine.domain.com}} for {{EX:localhost}}) where mentioned.
Note:It is recommended that you use the real machine name instead of localhost. The standard for cookies specifies that they can only be set when a domain name has at least two dots in it. If you use localhost, you will lose session information if you leave catalog, since the session ID is passed only as part of the URL.
H2:Starting or restarting Interchange
N:When you make changes to the configuration files you need to restart the Interchange server. How this is done depends on how you installed Interchange:
*{{B:RPM install as root:}} {{EX:/usr/sbin/interchange -r}}
*{{B:Manual install as Interchange user:}} {{EX:/usr/local/interchange/bin/interchange -r}}
*{{B:Manual install as root:}} {{EX:su interch -c '/usr/local/interchange/bin/interchange -r'}}
*{{B:Manual install as regular user:}} {{EX:~/interchange/bin/interchange -r}}
N:Find the right command for your system and remember it, since you will need to restart Interchange a few times during the tutorial.
H2:Tutorial assumptions
N:Because it is impossible to cover all scenarios, this tutorial assumes that you installed Interchange on Red Hat Linux from the RPM packages. This creates the following settings:
*{{B:Interchange software directory:}} /usr/lib/interchange
*{{B:Catalogs directory:}} /var/lib/interchange
*{{B:cgi-bin directory:}} /var/www/cgi-bin
*{{B:Interchange user:}} interch
*{{B:Demo catalog name:}} foundation
*{{B:Demo catalog URL base:}} http://localhost/cgi-bin/foundation
*{{B:Tutorial catalog name:}} tutorial
*{{B:Tutorial catalog URL base:}} http://localhost/cgi-bin/tutorial
*{{B:Tutorial catalog directory:}} /var/lib/interchange/tutorial
N:If you did not install with these settings, substitute the correct values for your system when these settings are mentioned in the tutorial.
H1:Building Your Catalog
N:This section describes the pages and directories that need to be established to create a properly functioning catalog.
H2:Create the link program
N:You need to make a copy of the demo link program in your cgi-bin directory and name it {{FILE:tutorial}}.
N:The demo link program has the same name as your demo catalog, usually {{EX:foundation}}. The link program links the Interchange daemon with your web server. Make sure that it has the same owner and file permissions as the one you copied from. The set-UID bit is especially (unless you installed as a regular user). Normally you will need to be root to have write permissions in the cgi-bin directory.
N:Type this command as root while in your cgi-bin directory:
E[keep_prev=1] cp -p foundation tutorial
N:If everything is working correctly, typing {{EX:ls -l}} should describe your files roughly like this:
!block example;
-rwsr-xr-x 1 interch interch 7708 Dec 16 22:47 foundation
-rwsr-xr-x 1 interch interch 7708 Dec 16 22:47 tutorial
!endblock
H2:Create the tutorial catalog directory
N:As root, create a subdirectory named {{FILE:tutorial}} under your catalogs directory (probably {{FILE:/var/lib/interchange/}}). This is where all of the catalog-specific files will go. It needs to be readable, writable, and executable by the Interchange user. This will be referred to as your catalog directory. Type the following while in the catalogs directory to create the tutorial subdirectory:
!block example;
mkdir tutorial
chown interch.interch tutorial
chmod 770 tutorial
!endblock
H2:Become the Interchange user
N:You should be able to do everything you need to do as the 'interch' user for the rest of this tutorial. So you can switch to that user now ({{EX:su - interch}}). If you installed Interchange from the RPM, the user {{B:interch}} probably doesn't have a password. You'll have to set it with a command such as {{EX:passwd interch}} while root.
H2:Go to the tutorial catalog directory
N:Change to the catalog directory with the 'cd' command. For the rest of this tutorial, all file locations will be given relative to the tutorial catalog directory. For example, {{FILE:pages/ord/basket.html}} would actually be {{FILE:/var/lib/interchange/tutorial/pages/ord/basket.html}} or the equivalent on your system. The only exception is {{FILE:interchange.cfg}}, which is in the Interchange software directory.
Note:To improve clarity, we will append a trailing slash to directory names to clearly distinguish them from file names. (Similar to the output of the {{FILE:ls}} command with the {{EX:-F}} option.)
H2:Create the session directory
N:You need to create the session directory where Interchange saves information on each visitor's browsing session. If you do not have this directory, your catalog will not work. This directory is called {{FILE:session/}} and goes under your catalog directory. Type {{EX:mkdir session}} to create this directory.
H1:Configuration files
N:Interchange configuration is controlled by a number of directives, which are specified in two files. Global configuration directives go in {{FILE:interchange.cfg}} in the Interchange software directory. Catalog-specific configuration directives go in {{FILE:catalog.cfg}} in the catalog directory.
N:A complete directive consists of the directive name followed by whitespace-separated parameters. Any number of spaces or tabs can be between the directive and its options, but the directive and its options must be on the same line. The directive is case-insensitive, but it is recommended that you use it consistently for readability.
N:You can insert blank lines or comment lines (lines where the first non-blank character is '#') throughout the configuration files to improve readability. The order the lines appear in is significant, but unimportant for the simple catalog you are creating.
N:For the next part, access your text editor (for example, vi, emacs, pico, joe, gedit, or nedit) to start editing some files.
H2:interchange.cfg
N:The first directive we need to use is a global directive that tells Interchange where the new catalog is, called {{1:Catalog}}. The {{2:Catalog}} directive has the following format:
E: Catalog name catalog_base_directory link_url_path
N:Open {{FILE:interchange.cfg}} in the Interchange software directory. Go near the top of the file, right below the other Catalog directives, and add this line:
E: Catalog tutorial /var/lib/interchange/tutorial /cgi-bin/tutorial
N:Save the file.
H2:catalog.cfg
N:For the rest of the tutorial, most of the files mentioned do not exist yet. You will create them yourself with initial text we give.
N:You need to create a {{FILE:catalog.cfg}} file for your tutorial store (in the tutorial catalog directory). We'll start with a very simple products database table with a few fields and a few products.
N:The {{2:Database}} directive describes a database table to the Interchange system in this format:
E: Database name filename format
N:Interchange has several database options available. We will use the simplest, which is the built-in default (specifically, some variant of DBM). The default location for {{1:filename}} is in a subdirectory called {{FILE:products}} under the catalog directory. Interchange recognizes a number of file formats. We will use a tab-delimited text file. Enter the following into {{FILE:catalog.cfg}}:
E: Database products products.txt TAB
N:This tells Interchange that you have a database table named 'products' that is described in a tab-delimited file named {{FILE:products.txt}}. You can describe an unlimited number of arbitrary database tables for the system to use this way. Interchange keeps a list of default tables called "Product Files," reflecting its e-commerce roots. You can specify all of the database tables that contain products by using the {{2:ProductFiles}} directive. There is no default for this, so you will have to specify your products table's name by adding the following line to {{FILE:catalog.cfg}}:
E: ProductFiles products
N:There are a few other directives that Interchange expects to see in order to complete the minimum configuration. They are {{2:VendURL}}, {{2:SecureURL}}, and {{2:MailOrderTo}}. They are, respectively, your catalog's base URL, its secure URL, and the e-mail address to mail order notices to. Add the following lines to {{FILE:catalog.cfg}} to establish these directives:
!block example;
VendURL http://localhost/cgi-bin/tutorial
SecureURL http://localhost/cgi-bin/tutorial
MailOrderTo [email protected]
!endblock
N:The {{FILE:catalog.cfg}} file should look like this when you save it:
!block example;
Database products products.txt TAB
ProductFiles products
VendURL http://localhost/cgi-bin/tutorial
SecureURL http://localhost/cgi-bin/tutorial
MailOrderTo [email protected]
!endblock
H1:The products database table
H2:products/products.txt
N:Create the {{FILE:products/}} directory in your tutorial catalog directory.
N:The {{FILE:products/products.txt}} file 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 parses the products.txt file, it will expect the first line to contain the names of the fields for the database table (for example, sku, description, price). The first field in the list is expected to be a primary key (unique identifier) for that row. In most cases you are going to use the SKU (stock keeping unit) as the unique identifier for each product.
N:The product database is handled as a special case since Interchange expects at least the description, price, and product ID (sku) fields. In other words, the {{FILE:products.txt}} file must at least contain fields named sku, price, and description. You can have other fields too, if you wish.
N:The simple store that we are going to build will sell tests. You can choose another sample product line, but it is recommended that you keep it simple. Create the file {{FILE:products/products.txt}} to look like this, with a single tab separating each field:
!block example;
sku description price
4595 Nice Bio Test 275.45
2623 Stack of Econ Quizzes 1.24
0198 Really Hard Physics Test 1589.34
1299 Ubiquitous diff eq final 37.00
!endblock
Note:When using tab-delimited files as we are, make sure you have exactly one tab between each field. Some text editors will use spaces to simulate tabs. Interchange expects actual ASCII tab characters; extra spaces or other characters will corrupt your data.
N: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.
H1:Page templates
N: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:
!block example;
_____________________
| |
| top |
| |
|---------------------|
| | |
| | |
| left | main |
| | |
| | |
|---------------------|
| |
| bottom |
|_____________________|
!endblock
N:The "main" section holds the content that is different for each page. The "top" section is for headers, banners, menus, and so on. The "left" section can be used as a sidebar or navigation bar, and the "bottom" 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.
N:Now type the HTML for each template section in an individual plain text file in the catalog directory, named 'top', 'left', and 'bottom', respectively using the code displayed below. No '.html' suffixes are used on these because they are not meant to be parsed directly by Interchange as full pages.
H2:top
!block example;
<html>
<head>
<title>The Interchange Test Catalog</title>
</head>
<body>
<div align=center>
<table width="80%" border cellpadding=15>
<tr><td colspan=2 align=center><h1>The Interchange Test Catalog</h1></td></tr>
!endblock
H2:left
!block example;
<tr>
<td align=center>(left)</td>
<td align=center>
!endblock
H2:bottom
!block example;
</td>
</tr>
<tr><td colspan=2 align=center>(bottom)</td></tr>
</table>
</div>
</body>
</html>
!endblock
H2:The Interchange Tag Language
N:Now we need a way to pull the template pieces we just created into the proper places to make a complete page. This is done using ITL, the Interchange Tag Language.
N:ITL is at the heart of almost all Interchange catalog pages. It's how you use Interchange's functionality. The ITL tags appear between square brackets like [this]. Options appear after the tag, separated by whitespace, like this: [tag option1 option2] and this: [tag option1=value1 option2=value2]. They can span multiple lines. (That can help readability when the tag has many options.) There are many ITL tags, and for this tutorial very few will be addressed. For a complete listing of the ITL tags, see the {{1:Interchange Tag Reference Guide}}.
N:Your first tag will be [include], which reads the file mentioned (relative to the catalog directory), parses any Interchange tags, and puts the result in place of the tag. This is demonstrated on the next page you need to create.
H1:Creating a welcome page
H2:pages/index.html
N:Create a directory called {{FILE:pages/}} in your tutorial catalog directory.
N:Type the following text and save it as {{FILE:pages/index.html}}. This will create a page to test that everything works so far.
!block example;
[include top]
[include left]
This is where your content goes.
[include bottom]
!endblock
N:Restart Interchange so your changes take effect. Go to your web browser and load the page. The URL should be similar to the following: {{EX:http://localhost/cgi-bin/tutorial/index.html}}.
Note:Interchange pages in the {{FILE:pages/}} or other directories {{B:must}} have the .html suffix on them. You can drop the suffix in your URL and in other places, such as the [page] tag you'll learn about later, but the file name on disk must have the suffix.
H1:Troubleshooting
N:Your first Interchange page should have displayed as described in your browser. 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.
N:The following is a troubleshooting checklist to use when you run into problems:
^Have you created directories with the proper names in the proper locations? (See Appendix A for a full directory and file structure of the tutorial catalog.)
+Have you misspelled any file names or put them in the wrong directories? Are the files and parent directories readable by the {{EX:interch}} user? Double-check with the {{FILE:ls}} command.
+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.
+Did you type all punctuation, ITL tags, and HTML tags correctly?
+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).
+Did you restart Interchange if you changed anything in {{FILE:interchange.cfg}} or {{FILE:catalog.cfg}}, or if you're in a high-traffic mode?
+Check your catalog error log, {{FILE:error.log}} in your tutorial catalog directory, to see if Interchange reported any errors.
+Check the Interchange server error log, {{FILE:error.log}} in the Interchange software directory, to see if it had problems loading the catalog at all.
+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.
H1:Displaying products
H2:Listing all products
N:Now that your store is running, you need to display your products on the welcome page. We will loop over all of the products in our database and produce an entry for each one in a table. Replace the line "This is where your content goes" in {{FILE:pages/index.html}} with the following:
!block example;
<table cellpadding=5>
<tr>
<th>Test #</th>
<th>Description</th>
<th>Price</th>
</tr>
. . .
</table>
!endblock
N:Now we will use Interchange tags to fill in the rest of the table from the products database you created. The [loop] [/loop] ITL tag pair tells Interchange to iterate over each item in the parameter list. In this case, the loop is over the result of an Interchange search. The search parameter does a database search on the provided parameters. In this case, we're doing a very simple search that returns all of the fields for all of the entries in the products database. The parameters passed to the search tell Interchange to {{1:return all}} ('ra') on the file ('fi') {{1:products}} respectively. The following should take the place of the ellipsis in the code you placed in {{FILE:index.html}}:
!block example;
[loop search="ra=yes/fi=products"]
. . .
[/loop]
!endblock
N:In the loop we just established, the individual elements of the entry using the [loop-field] tag. The following code should replace the above ellipsis in the code we placed in {{FILE:pages/index.html}}:
!block example;
<tr>
<td>[loop-code]</td>
<td>[loop-field description]</td>
<td align=right>[loop-field price]</td>
</tr>
!endblock
N:The [loop-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 [loop-field sku] tag, because the 'sku' field is the primary key 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.
N:Your finished page should look like this:
!block example;
[include top]
[include left]
<table cellpadding=5>
<tr>
<th>Test #</th>
<th>Description</th>
<th>Price</th>
</tr>
[loop search="ra=yes/fi=products"]
<tr>
<td>[loop-code]</td>
<td>[loop-field description]</td>
<td align=right>[loop-field price]</td>
</tr>
[/loop]
</table>
[include bottom]
!endblock
N:Test this page by refreshing the {{EX:index.html}} page in your browser.
H2:pages/flypage.html
N:The next step is to create an individual page for each item. To do this, you need to create a special generic page called {{FILE:pages/flypage.html}}. When a page is requested that does not exist in the {{FILE:pages/}} directory, Interchange will check and see if the requested page has the same name as a product ID from the product database table (in this case a SKU). If it does, it will show the flypage for that product. If there's no product with that ID, the special error page {{FILE:special_pages/missing.html}} (described in the next section) will be displayed.
N:For example, if the page {{FILE:0198.html}} was requested, Interchange first checks for a page with that name. If one is not found, it searches the products database table for a product with that ID. Interchange then creates a product page "on the fly" using {{FILE:pages/flypage.html}}. When constructing the flypage, the entire product record for the requested product is available through the [item-field] tag (similar to the [loop-field] tag). To create a fly page, type the following code and save it as {{FILE:pages/flypage.html}}.
!block example;
[include top]
[include left]
<h3>Test #[item-code]</h3>
<p>[item-field description] . . . [item-field price]</p>
[include bottom]
!endblock
N:Then, to provide links to the product flypages from your home page, modify {{FILE:pages/index.html}} slightly, so that:
!block example;
<td>[loop-field description]</td>
!endblock
N:becomes:
!block example;
<td><a href="[loop-code].html">[loop-field description]</a></td>
!endblock
H2:special_pages/missing.html
N:Create the {{FILE:special_pages/}} directory in your tutorial catalog directory (not in the {{FILE:pages/}} directory).
N:As mentioned, 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 {{FILE:special_pages/missing.html}}.
!block example;
[include top]
[include left]
<p>We're sorry, the page you requested has not been found.</p>
<p>Try finding what you need on the [page index]welcome page</a>.</p>
[include bottom]
!endblock
N:The addition of this page ensures that users see your error message instead of a mysterious server error if they mistype a URL.
H1:The shopping basket
H2:A link for ordering
N:Now that you have your products available, let's add a shopping cart so customers can purchase them. This is created using the [order] tag. These tags create an HTML link that causes the specified item to be ordered and transfers the shopper to the basket page. This is a built-in shortcut to the complete order process which uses an HTML form submission process. The parameter for the [order] tag is the product ID. To add these tags to the catalog, make the following change to {{FILE:pages/index.html}}:
!block example;
<tr>
<td>[loop-code]</td>
<td>[loop-field description]</td>
<td align=right>[loop-field price]</td>
+ <td>[order [loop-code]]Order Now</a></td>
</tr>
[/loop]
!endblock
Note:The 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 context. This style is called a "context diff" and is used often in this tutorial.
H2:pages/ord/basket.html
N:Create the directory {{FILE:pages/ord/}} in the tutorial catalog directory. In other words, {{FILE:ord/}} should be inside the {{FILE:pages/}} directory.
N:For the [order] tag, Interchange expects a default page called {{FILE:pages/ord/basket.html}}. This page displays the contents of the shopping basket and contains other shopping basket functionality.
N:The Foundation store 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 an [item] prefix. Put the following code in the new file {{FILE:pages/ord/basket.html}}. The section that follows explains the tags used.
!block example;
[include top]
[include left]
<h2>This is your shopping cart!</h2>
<table cellpadding=5>
<tr>
<th>Qty.</th>
<th>Description</th>
<th>Cost</th>
<th>Subtotal</th>
</tr>
[item-list]
<tr>
<td align=right>[item-quantity]</td>
<td>[item-field description]</td>
<td align=right>[item-price]</td>
<td align=right>[item-subtotal]</td>
</tr>
[/item-list]
<tr><td colspan=4></td></tr>
<tr>
<td colspan=3 align=right><strong>Total:</strong></td>
<td align=right>[subtotal]</td>
</tr>
</table>
<hr>
<p>
[page checkout]Purchase now</a><br>
[page index]Return to shopping</a>
</p>
[include bottom]
!endblock
N:The basket items can be accessed one at a time by using the [item-list] tag. So we will create a table by iterating through the basket items. The text within the [item-list] [/item-list] tags is created for each item in the list.
*[item-quantity] shows the quantity of the item ordered. If the same item is ordered multiple times, the quantity increases.
*[item-field description] 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.
*[item-price] shows the per-item price that is defined in the product database table.
*[item-subtotal] 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.
*[subtotal] shows the calculated shopping basket subtotal.
*[page index] creates the starting HTML <a href="..."> for a link to the catalog welcome page.
N: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 {{FILE:pages/index.html}} by adding the following lines.
!block example;
</table>
+ <hr>
+ <p align=center>[page order]View shopping cart</a></p>
[include bottom]
!endblock
N:Refresh the page and test the shopping basket in your browser.
H1:Order checkout
H2:pages/checkout.html
N: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.
N:First you 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 could 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.
N:To create a checkout page, type the following code and save it as {{FILE:pages/checkout.html}}. The section that follows explains the code.
!block example;
[include top]
[include left]
<h1>Checkout Page</h1>
<form method=post action="[process]">
<input type=hidden name=mv_todo value=submit>
<input type=hidden name=mv_order_profile value=order_profile>
<input type=hidden name=mv_cyber_mode value=minivend_test>
<table cellpadding=3>
<tr>
<td align=right><b>First name:</b></td>
<td><input type=text name=fname value="[value fname]"></td>
</tr>
<tr>
<td align=right><b>Last name:</b></td>
<td><input type=text name=lname value="[value lname]"></td>
</tr>
<tr>
<td align=right rowspan=2><b>Address:</b></td>
<td><input type=text name=address1 value="[value address1]"></td>
</tr>
<tr>
<td><input type=text name=address2 value="[value address2]"></td>
</tr>
<tr>
<td align=right><b>City:</b></td>
<td><input type=text name=city value="[value city]"></td>
</tr>
<tr>
<td align=right><b>State:</b></td>
<td><input type=text name=state value="[value state]"></td>
</tr>
<tr>
<td align=right><b>Postal code:</b></td>
<td><input type=text name=zip value="[value zip]"></td>
</tr>
<tr>
<td align=right><b>Country:</b></td>
<td><input type=text name=country value="[value country]"></td>
</tr>
</table>
<p>
Note: We assume that your billing address is the same as your shipping address.
</p>
<table cellpadding=3>
<tr>
<td align=right><b>Credit card number:</b></td>
<td><input type=text name=mv_credit_card_number value="" size=20></td>
</tr>
<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>
</td>
</tr>
</table>
<p>
<input type=submit name=submit value="Finalize!">
<input type=reset name=reset value="Reset">
</p>
</form>
<p>[page index]Return to shopping instead</a></p>
[include bottom]
!endblock
N: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 [process] 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 {{FILE:special_pages/receipt.html}} page, which is described later.
N:You are submitting some hidden form values that will tell Interchange how to process this form. The first value, {{2:mv_todo}} was set as {{1:submit}}. This causes the form to be submitted for validation. The second value, {{2:mv_order_profile}} was set as {{1:order_profile}}. This determines the validation process for the form. It is explained further in the next section.
N:The last value, {{2:mv_cyber_mode}}, was set to be {{1:minivend_test}}. The {{2:mv_cyber_mode}} value determines what method will be used to charge a credit card. The value of {{1:minivend_test}} uses the internal test method, which calculates a simple checksum against the card to determine if it is a valid number.
N:When preparing an order for processing, Interchange looks for certain named fields in the form values for name, address, and credit card information. We are using all expected field names in this form so that no translation needs to take place.
N:View the checkout page in your browser. The "Finalize!" link has not been enabled, but the page should display properly.
H2:etc/profiles.order
N:Create the {{FILE:etc/}} directory in the tutorial catalog directory now.
N: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 verification page by typing the following and saving it as {{FILE:etc/profiles.order}}. The section that follows explains the code used.
!block example;
__NAME__ order_profile
fname=required
lname=required
address1=required
city=required
state=required
zip=required
&fatal=yes
&final=yes
__END__
!endblock
N:A single file can contain multiple profile definitions. First the profile is named using the __NAME__ pragma. (This is unrelated to the __VARIABLE__ syntax seen elsewhere in Interchange.) Then in the profile there is a list of the form fields that are required. The {{2:&fatal}} setting indicates that validation will fail if any of the requirements are not met. {{2:&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 __END__ pragma signals the end of this profile, after which you can begin another one.
N:In order to activate your order profile, add the following {{2:OrderProfile}} directive to the end of {{FILE:catalog.cfg}}:
!block example;
OrderProfile etc/profiles.order
!endblock
Watch for white space in front of the __NAME__ pragma, it can cause your
profile to be ignored. Rember to restart Interchange for any changes to
take effect.
H2:special_pages/needfield.html
N:If the submitted form lacks a required field, Interchange will display an error page. The default location is {{FILE:special_pages/needfield.html}}. To create this page, type the following text and save it as {{FILE:special_pages/needfield.html}}.
!block example;
[include top]
[include left]
<p>The following information was not given:</p>
<p><b>[error all=1 show_var=1 show_error=1 joiner='<br>']</b></p>
<p>Please go back to the [page checkout]checkout page</a>
and fill out the form properly.</p>
[include bottom]
!endblock
N:The [error] tag is the most important tag on this page. The {{2:all}} parameter tells the tag to iterate through all of the errors reported from the failed verification, and the {{2:show_var}} parameter indicates that the failed variable name should be displayed. For example, if the first name was left empty, {{1:fname}} would be shown. The {{2:show_error}} parameter displays the actual error for the variable. The {{2:joiner}} parameter inserts an HTML {{1:<br>}} tag between each error message, so each error is displayed on its own line. In more complex configurations, the [error] tag can be even more expressive.
H2:Credit card processing
N:This tutorial uses a very simple order process. To accomplish this, one more directive needs to be added to the file {{FILE:etc/profiles.order}}:
!block example;
&fatal=yes
&final=yes
+ &credit_card=standard keep
__END__
!endblock
N:This issues two instructions to the credit card system.
N:The first option, {{2: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.
N:The second option, {{2: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.
N: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).
H2:etc/report
N:When the customer's involvement in the order is complete, Interchange composes an email and sends it to the recipient defined in the MailOrderTo directive in {{FILE:catalog.cfg}}. The default location for the template for this email report is {{FILE:etc/report}}. Interchange tags can be used to fill in the body of the message.
N: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 {{FILE:etc/report}}.
!block example;
Name: [value fname] [value lname]
Address: [value address1][if value address2]
[value address2][/if]
City, State, etc.: [value city], [value state] [value zip] [value country]
Credit Card #: [cgi mv_credit_card_number]
Expiration Date: [cgi mv_credit_card_exp_month]/[cgi mv_credit_card_exp_year]
************ ORDER ************
[item-list]
[item-quantity] x [item-description] ([item-code]), [item-price] ea.
[/item-list]
Subtotal: [subtotal]
Total: [total-cost]
!endblock
N:This file is in plain text format where, unlike HTML, white space is relevant. It is fairly straightforward, except that the [if] tag was added to only include the optional second address line if the customer filled it in.
N:One of the special properties of the {{1:mv_credit_card_number}} field is that Interchange specifically precludes the credit card number from being saved. This makes it unavailable to you in the [value] tag. The {{2:[cgi]}} tag is used to circumvent this important security measure in order to get the value submitted from the last form.
N:{{B:WARNING!}} 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.
H2:special_pages/receipt.html
N: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 {{FILE:special_pages/receipt.html}}. To create a receipt page, type the following code and save it as {{FILE:special_pages/receipt.html}}.
!block example;
[include top]
[include left]
<p>Thank you for ordering stuff from us.<br>Have a nice day!</p>
<p>[page index]Return to our welcome page</a></p>
[include bottom]
!endblock
N:Once the order is processed, the customer's shopping cart is emptied.
N:At this point you have a more-or-less functional store. Congratulations.
H1:Enhancing the catalog
N: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 more enhancements you can attempt on your own.
H2:Price pictures
N: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 {{1:price pictures}}.
N: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 {{EX: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 {{FILE:catalog.cfg}} file:
!block example;
Locale en_US currency_symbol $
!endblock
N:Restart Interchange and view your catalog. You will notice little has changed on the welcome page or the flypages, but in the shopping cart all your prices should be formatted as U.S. dollars ("1347.3" has become "$1,347.30"). This is because Interchange automatically formats shopping cart prices as currency. To turn off this feature, you would have to change the [item-price] tag to [item-price noformat] in {{FILE:pages/ord/basket.html}}.
N:But that's probably not what you want to do. You're probably more interested in formatting your other prices as currency. To do that, simply use the [currency] [/currency] tag pair for all price values. Make the following change to {{FILE:pages/index.html}}:
!block example;
[loop search="ra=yes/fi=products"]
<tr>
<td>[loop-code]</td>
<td>[loop-field description]</td>
- <td align=right>[loop-field price]</td>
+ <td align=right>[currency][loop-field price][/currency]</td>
</tr>
[/loop]
!endblock
Note:The line that begins with '-' should be deleted. Do not type the '-'. The next line, that starts with '+', replaces it.
N:A similar change to the {{EX:[item-field price]}} tag in the {{FILE:pages/flypage.html}} page will fix that currency display. View the page in your browser. All your prices should be formatted for U.S. currency.
N:If your prices are not being formatted correctly, your default system locale may be set up differently or your {{EX:en_US}} locale settings may be wrong. There are a few other {{FILE:catalog.cfg}} directives you can use to correct the situation:
E: Locale en_US p_cs_precedes 1
N:Makes the currency symbol precede the currency value. A '0' setting makes the symbol come after the currency value.
E: Locale en_US mon_thousands_sep ,
N:Sets your thousands separator to a comma. It can be set to any value.
E: Locale en_US mon_decimal_point .
N:Sets your decimal separator to a comma. Many countries use a comma instead of a period to separate the integer from the decimal part.
Note:Consult the Interchange documentation and your operating system manual for more information on locale settings.
H2:Catalog variables
N:Interchange provides a very useful feature that has not been discussed yet called catalog variables. It provides a way for you to set a variable to a certain value in the {{FILE:catalog.cfg}} file and use it anywhere in your catalog pages. The {{2:Variable}} 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:
E: Variable SOMENAME whatever value you want
N:To access that variable in your pages, type the token __SOMENAME__. Notice that there are two underscore characters before the variable name and two after it, and that in place of the word SOMENAME 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 value can also include Interchange tags to be parsed.
H2:A more interesting page footer
N: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 {{FILE:catalog.cfg}}:
E: Variable CONTACT_EMAIL [email protected]
N:Now make the following change to your template file {{FILE:bottom}}:
!block example;
</td>
</tr>
- <tr><td colspan=2>(bottom)</td></tr>
+ <tr><td colspan=2><a href="mailto:__CONTACT_EMAIL__">Contact us</a>
+ if you have any questions.</td></tr>
</table>
</div>
</body>
</html>
!endblock
N:Be sure to restart Interchange before reloading the page in your browser, since you made a change to {{FILE:catalog.cfg}}.
N: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 {{FILE:catalog.cfg}}:
E: Variable DISPLAYDATE [time]%A, %B %d, %Y[/time]
Note:See the {{1:Interchange Tag Reference Guide}} for an explanation of the [time] tag.
N:Now add the following to the {{FILE:left}} template piece:
!block example;
<tr>
- <td align=center>(left)</td>
+ <td align=center>__DISPLAYDATE__</td>
<td align=center>
!endblock
N:Restart Interchange and view the page.
H2:Advanced credit card expiration date selection
N:To reduce the possibility of human error at checkout time, most online 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. It also lets you avoid explaining whether the user should enter a 2- or 4-digit year.
N:Make the following change to your {{FILE:pages/checkout.html}} page. The section that follows explains the code. 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 `backticks`.
!block example;
<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>
+
+ Month:
+ <select name=mv_credit_card_exp_month>
+ [loop
+ lr=1
+ option=mv_credit_card_exp_month
+ list="
+ 1 01 - January
+ 2 02 - February
+ 3 03 - March
+ 4 04 - April
+ 5 05 - May
+ 6 06 - June
+ 7 07 - July
+ 8 08 - August
+ 9 09 - September
+ 10 10 - October
+ 11 11 - November
+ 12 12 - December"]
+ <option value="[loop-code]">[loop-pos 1]
+ [/loop]
+ </select>
+
+ Year:
+ <select name=mv_credit_card_exp_year>
+ [comment]
+ This should always return the current year as the first, then
+ seven more years.
+ [/comment]
+ [loop option=mv_credit_card_exp_year lr=1 list=`
+ my $year = $Tag->time( '', { format => '%Y' }, '%Y' );
+ my $out = '';
+ for ($year .. $year + 7) {
+ /\d\d(\d\d)/;
+ $last_two = $1;
+ $out .= "$last_two\t$_\n";
+ }
+ return $out;
+ `]
+ <option value="[loop-code]">[loop-pos 1]
+ [/loop]
+ </select>
+
</td>
</tr>
</table>
!endblock
N:In the first set of <select> </select> tags a list is generated of the months to choose from. This is accomplished by using a {{2:[loop]}} tag. In this case we are looping over an explicit list. The list is provided in the {{1:list}} parameter. Use caution when typing this, as it is sensitive to formatting (which may not be reflected in this document). Make sure that the numbers are the first characters on each new line and that the elements are separated by a single tab. Since the columns in this list are not named, the first element can be accessed using {{2:[loop-code]}} or {{2:[loop-pos 0]}} with subsequent elements being accessed by {{2:[loop-pos N]}} where N is the number of the element you want. Notice that the elements are zero-indexed. Each time through this loop Interchange generates a select <option> with a number as the value and the name of the month as the text for the select menu.
N:For the next set of <select> </select> tags embedded Perl is used to generate the list which is iterated over. Perl code can be embedded in Interchange pages in order to extend the abilities of the system. Make sure you typed backticks (grave accents) after "list=" and before the closing bracket and not apostrophes. This code generates an entry for seven years in addition to the current year. It is not necessary at this point for you to understand this Perl code.
H2:Sorting the product list
N:The products listed on your welcome page are shown in the same order that you entered them into {{FILE:products/products.txt}}. As you add more products, you will want this list to show up in a predictable order. To do this, you need to change the search parameters in {{FILE:index.html}}, which were originally:
E: [loop search="
E: ra=yes
E: fi=products
E: "]
N:You will recall that 'ra' stands for 'return all' and 'fi' stands for file. Let's add the search parameter 'tf', which specifies the sor{{B:t f}}ield. You can specify the field either by name or by number (starting with 0), with names and order as given in the first line of {{FILE:products/products.txt}}). Make the following change in {{FILE:index.html}}:
E: [loop search="
E: ra=yes
E: fi=products
E: tf=price
E: "]
N:Refresh your browser. The default ordering is done on a character-by-character basis, but we were looking to do a numeric sort. For this you need to set 'to', the sor{{B:t o}}rder, to 'n', for {{1:numeric}}:
E: [loop search="
E: ra=yes
E: fi=products
E: tf=price
E: to=n
E: "]
N:Refresh your browser. Now try reversing the sort order by adding 'r' to the 'to' setting:
E: [loop search="
E: ra=yes
E: fi=products
E: tf=2
E: to=nr
E: "]
N:You'll notice that it worked equally well to specify the sort field by number instead of name. You could also do a reverse alphabetical sort by description:
E: [loop search="
E: ra=yes
E: fi=products
E: tf=1
E: to=r
E: "]
N:Now let's try narrowing the search down a bit. Instead of returning all, we'll give 'se', the {{B:se}}arch parameter, and and use 'su', which allows {{B:su}}bstring matches. To search only for products that have the word "test" in one of their fields, and sort the results by description, type:
E: [loop search="
E: se=test
E: su=yes
E: fi=products
E: tf=description
E: "]
N:Which seems like something that would be better done in a search box for your store visitors.
N:Before moving on, change this search back to the simple list, sorted by description:
E: [loop search="ra=yes/fi=products/tf=description"]
H2:Adding a search box
N:Your customers might appreciate the ability to search for a test by SKU or part of the test description. To do this, you need to add a search box to the left portion of the page layout. Make the following change to the file {{FILE:left}}:
!block example;
<tr>
- <td align=center>__DISPLAYDATE__</td>
+ <td align=center>
+ <form action="[area search]" method=post>
+ Search:<br>
+ [set testname]
+ su=yes
+ fi=product
+ sf=sk
+ sf=descriptio
+ [/set]
+ <input type=hidden name=mv_profile value=testname>
+ <input type=text name=mv_searchspec size=15 value="">
+ </form>
+ <hr>
+ __DISPLAYDATE__
+ </td>