5. Interchange Perl Objects

You can access all objects associated with the catalog and the user settings with opcode restrictions based on the standard Perl module Safe.pm. There are some unique things to know about programming with Interchange.

Under Safe, certain things cannot be used. For instance, the following can not be used when running Safe:

   $variable = `cat file/contents`;

The backtick operator violates a number of the default Safe opcode restrictions. Also, direct file opens can not be used. For example:

   open(SOMETHING, "something.txt")
       or die;

This will also cause a trap, and the code will fail to compile. However, equivalent Interchange routines can be used:

   # This will work if your administrator doesn't have NoAbsolute set
   $users = $Tag->file('/home/you/list');

   # This will always work, file names are based in the catalog directory
   $users = $Tag->file('userlist');

The following is a list of Interchange Perl standard objects are:

$CGI

            <INPUT TYPE=hidden NAME=foo VALUE=bar>
            <% $Document->write("Value of foo is $CGI->{foo}"); %>

$CGI_array

            <INPUT TYPE=hidden NAME=foo VALUE='bar'>
            <INPUT TYPE=hidden NAME=foo VALUE='baz'>
            <% = "The values of foo are", join (' and ', @{$CGI_array->{'foo'}}) %>

$Carts

            {
                'main' => [
                            {
                                'code' => '00-0011',
                                'mv_ib' => 'products',
                                'quantity' => 1,
                                'size' => undef,
                                'color' => undef
                            },
                            {
                                'code' => '99-102',
                                'mv_ib' => 'products',
                                'quantity' => 2,
                                'size' => 'L',
                                'color' => 'BLUE'
                            }
                        ],
                'layaway' => [
                            {
                                'code' => '00-341',
                                'mv_ib' => 'products',
                                'quantity' => 1,
                                'size' => undef,
                                'color' => undef
                            }
                        ]
            }

$Config

    # Allow searching the User database this page only
    $Config->{NoSearch} =~ s/\buserdb\b//;

%Db

            $ref = $Db{products};
            # access an element of the table
            $field = $ref->field($key, $column);
        
            # set an element of the table
            $ref->set_field($key, $column_name, $value);
        
            # atomic increment of an element of the table
            $ref->inc_field($key, $column_name, 1);
        
            # see if element of the table is numeric
            $is_numeric = $ref->numeric($column_name);
        
            # Quote for SQL query purposes
            $quoted = $ref->quote($value, $column_name);
        
            # Check configuration of the database
            $delimiter = $ref->config('DELIMITER');
        
            # Find the names of the columns (not including the key)
            @columns = $ref->columns();
            # Insert the key column name
            unshift @columns, $ref->config('KEY');
        
            # See if a column is in the table
            $is_a_column = defined $ref->test_column($column_name);
        
            # See if a row is in the table
            $is_present = $ref->record_exists($key);
        
            # Create a subroutine to return a single column from the table
            $sub = $ref->field_accessor($column);
            for (@keys) {
                push @values, $sub->($key);
            }
        
            # Create a subroutine to set a single column in the database
            $sub = $ref->field_settor($column);
            for (@keys) {
                $sub->($key, $value);
            }
        
            # Create a subroutine to set a slice of the database
            $sub = $ref->row_settor(@columns);
            for (@keys) {
                $sub->($key, @values);
            }
        
            # Return a complete array of the database (minus the key)
            @values = $ref->row($key);
        
            # Return a complete hash of the database row (minus the key)
            $hashref = $ref->row_hash($key);
        
            # Delete a record/row from the table
            $ref->delete_record($key);

%Sql

          <%
            my $dbh = $Sql{products}
                or return HTML "Database not shared.";
            my $sth = $dbh->prepare('select * from products')
                or return HTML "Couldn't open database.";
            $sth->execute();
            my @record;
            while(@record = $sth->fetchrow()) {
                foo();
            }
            $sth = $dbh->prepare('select * from othertable')
                or return HTML "Couldn't open database.";
            $sth->execute();
            while(@record = $sth->fetchrow()) {
                bar();
            }
          %>

$DbSearch

            array    Returns a reference to an array of arrays (best)
            hash     Returns a reference to an array of hashes (slower)
            list     Returns a reference to an array of tab-delimited lines
            $DbSearch->{table} = $Db{foo};
        
            $search = {
        
                    mv_searchspec => 'Mona Lisa',
                    mv_search_field => [ 'title', 'artist', 'price' ],
                    mv_return_fields    => [ 'title' ]
        
                };
        
            my $ary = $DbSearch->array($search);
        
            if(! scalar @$ary) {
                return HTML "No match.\n";
            }
        
            for(@$ary) {

$Document

         HTML $foo;                     # Append $foo to the write buffer array
         $Document->write($foo);        # object call to append $foo to the write
                                        # buffer array
         $Document->insert($foo);       # Insert $foo to front of write buffer array
         $Document->header($foo, $opt); # Append $foo to page header
         $Document->send();             # Send write buffer array to output, done
                                        # automatically upon end of ASP, clears buffer
                                        # and invalidates $Document->header()
         $Document->hot(1);             # Cause writes to send immediately
         $Document->hot(0);             # Stop immediate send
         @ary = $Document->review();    # Place contents of write buffer in @ary
         $Document->replace(@ary)       # Replace contents of write buffer with @ary
         $ary_ref = $Document->ref();   # Return ref to output buffer

$Document->write($foo)

$Document->insert($foo)

            $Document->write("23");
            $Document->insert("1");
            $Document->send();
            $Document->write("23");
            $Document->write("1");
            $Document->send();

$Document->header($foo, $opt)

            $Document->header("Content-type: text/plain");
            $Document->header("Content-type: text/plain", { replace => 1 } );

$Document->hot($foo)

$Document->send()

$Document->review()

            @ary = $Document->review();

$Document->replace(@new)

$Document->ref()

            # Remove the first item in the write buffer
            my $ary_ref = $Document->ref();
            shift @$ary_ref;

HTML

            HTML $foo, $bar;
            $Document->write($foo, $bar);

$Items

$Scratch

           <% $Scratch->{foo} = 'bar'; %>
            [set foo]bar[/set]

$Session

            <%
                my $out = $Session->{browser};
                $Document->write($out);
            %>
            [data session browser]
            <%
                $Session->{source} = 'New_partner';
            %>

$Tag


IMPORTANT NOTE: If the tag will access a database that has not been previously opened, the table name must be passed in the ASP call. For example:

            [mvasp tables="products pricing"]
            [mvasp products pricing]
            <%
                my $user = $Session->{username};
                my $name_from_db = $Tag->data('userdb', 'name', $user );
                $Document->write($name_from_db);
            %>
            [data table=userdb column=name key="[data session username]"]
            # WRONG!!!
            $Tag->shipping-desc('upsg');
            # Right
            $Tag->shipping_desc('upsg');
            $Tag->data('products', 'title', '00-0011');
            my $opt = {
                            table   => 'products',
                            column  => 'title',
                            key     => '00-0011',
                        };
        
            $Tag->data( $opt );
            $Tag->item_list( {
                                'body' => "[item-code] [item-field title]",
                            });
            $Tag->item_list( { }, "[item-code] [item-field title]")

$Values

            <% $Document->write($Values->{foo}); %>
            [value foo]

&Log

            <%
                Log("error log entry");
            %>
            <%
                Log("\\error log entry without timestamp");
                Log('\another error log entry without timestamp');
                Log("error log entry with timestamp");
            %>