Catalog Script: catalog.cgi

This script prints the catalog listing, individual catalog entries, and handles the shopping cart.

#!/usr/local/bin/perl
# catalog.cgi
# An online catalog/shopping cart demo.  Uses DBI and CGI.pm.

use lib 'modules';

use DBI;
use CGI::Pretty qw/:standard/;
use Catalog;
use ShoppingCart;
use strict;

use constant DB           => 'dbi:mysql:perl_conference';
use constant stylesheet   => '/stylesheets/catalog.css';

# open database
my $db = DBI->connect(DB,undef,undef,{PrintError=>0}) || die $DBI::errstr;

# CGI parameters:
# -none-             display catalog table o' contents (in no particular order)
# "catno"            display catalog entry for indicated item
# "catno" "add"      add catalog item to shopping cart
# "catno" "delete"   delete catalog item from shopping cart

# Basic variables.  Note that if we can't get a shopping cart object, we just exit.
# This is because the shopping cart generates an HTTP redirection automatically.
my $cart    = ShoppingCart->new($db) || exit 0;
my $catalog = Catalog->new($db)      || die "Couldn't create catalog";
my $catno   = param('catno') unless param('browse');
my $title   = $catno ? "Catalog \#$catno" : 'Kool Kitchen Koncepts';
    
# process adds/deletes on the shopping cart
process_shopping_cart($catno,$cart) if $catno;

# begin the page
print header(),  # start HTTP
      start_html(-Style => {src => stylesheet},
		 -Title => $title);

# display the requested item
if ($catno) {
    display_item($catalog,$cart,$catno);
} else { # no item requested, so display table o' contents
    display_list($catalog,$cart);
}

# display the shopping cart, if there is one
display_shopping_cart($catalog,$cart);

bottom_boilerplate();
print end_html;
$db->disconnect;
exit 0;

# Display a list of items in the catalog
sub display_list {
    my ($catalog,$cart) = @_;

    print h1('Our Katalog of Fine Kitchen Kitsch');
    my $items = $catalog->list;
    
    my ($count,@rows);
    for my $catno (sort {$items->{$a} cmp $items->{$b}} keys %$items) {
	my $class = $count++ % 2 ? '' : 'highlight'; # alternate highlight rows
	my $url = $cart->rewrite_url(url() . "?catno=$catno");

	push(@rows,
	     td ({-class=>$class},
		 [$items->{$catno},a({-href=>$url},$catno)])
	     );
    }

    print table({-width=>'100%'},
		 TR(th['Description','Catalog']),TR \@rows);
}

# display a selected catalog item
sub display_item { 
    my ($catalog,$cart,$catno) = @_;
    my $info = $catalog->info($catno) || not_found_error($catno);
    my $url = url(-path_info=>1);

    print h1($info->{'name'});
    print img({-alt=>"[$catno]",
	       -src=>$cart->rewrite_url("display.cgi?catno=$catno"),-align=>'LEFT'})
	if $info->{'image'};

    my $left = $cart->items_left($catno);
    print p($info->{'description'}),
	  p(strong('Price:'),"\$$info->{price}",
         $left > 0 ? em('(In stock)') : strong({-class=>'alert'},'Out of stock'));
 
    # handle the shopping cart stuff
    my $cart_data = $cart->fetch;
    print start_form(-action=>url(-path_info=>1)),
          hidden(-name=>'catno'),
          submit(-name=>'browse',-value=>'Browse Catalog');
    print submit(-name=>'delete',-value=>'Delete from Shopping Cart')
	if $cart_data->{$catno} > 0;
    print submit(-name=>'add',   -value=>'Add to Shopping Cart'),
          end_form;
}

# display the current shopping cart
sub display_shopping_cart {
    my ($catalog,$cart) = @_;
    my $url = url(-relative=>1);
    my $items = $cart->fetch;
    my @rows;
    for my $catno (keys %$items) {
	my $name = $catalog->info($catno)->{'name'};
	my $left = $cart->items_left($catno);
	my $backordered = $left >= 0 ? cite('in stock') : strong({-class=>'alert'},abs($left));
	push(@rows,td({-align=>'LEFT'},
		      [ a({-href=>$cart->rewrite_url("$url?catno=$catno")},$catno),
		       $name,
		       textfield(-name=>$catno,-value=>$items->{$catno},
				 -override=>1,-size=>4)]) .
	     td({-align=>'CENTER'},$backordered));
    }
    return unless @rows;
    print hr,
          h2('Your Shopping Cart'),
          start_form({-action=>$cart->rewrite_url('order.cgi')}),
          table({-border=>undef},
		TR(th ['Catalog','Description','Quantity','Backordered']),
		TR \@rows),
          submit('Place Order'),
          end_form;
}

# Process the "add" and "delete" shopping cart buttons
sub process_shopping_cart {
    my ($catno,$cart) = @_;
    return unless param('add') || param('delete');
    my $current = $cart->fetch;
    $current->{$catno}++      if param('add');
    $current->{$catno}=0      if param('delete');
    $cart->store($current);
}

# Error message to display if the requested catalog number does not exist
# (?someone screwing around with our URL?).
sub not_found_error {
    my $catno = shift;
    print start_html(-style => {src => stylesheet},
		     -title => 'Unknown Product'),
          h1('Unknown Product'),
          p("The product with catalog number $catno is not on our current",
	    "stocklist.  Please call our customer service representatives");
    bottom_boilerplate();
    exit 0;
}

sub bottom_boilerplate {
    print hr,'Copyright 1999 ',a({-href=>'/'},'Kool Kitchen Concepts');
}
  


Watch it run


<< Previous
Contents >> Next >>

Lincoln D. Stein, lstein@cshl.org
Cold Spring Harbor Laboratory
Last modified: Sun Jun 4 13:09:48 PDT 2000