There are dozens of MiniVend pre-defined tag functions. If you don't see
just what you need, you can use USER DEFINED TAGS
to create tags just as powerful as the pre-defined ones.
There are two styles of tag -- HTML/new, and old. Old style is a legacy from prior versions of MiniVend and is no longer in standard use, but its positional syntax can usually still be used in New/HTML mode for convenience.
In the new style, you can specify constructs inside an HTML tag:
<TABLE MV="if items"> <TR MV="item-list"> <TD> [item-code] </TD> <TD> [item-description] </TD> <TD> [item-price] </TD> </TR></TABLE>
The above will loop over any items in the shopping cart, displaying their part number, description, and price, but only IF there are items in the cart.
The same thing can be achieved with:
[if items] <TABLE> [item-list] <TR> <TD> [item-code] </TD> <TD> [item-description] </TD> <TD> [item-price] </TD> </TR> [/item-list]</TABLE> [/if]
To use the new more regular syntax by default, set the NewTags
directive to Yes
. The demo catalog is distributed with NewTags Yes
starting at MiniVend 3.07.
In most cases, tags specified in the old positional fashion will work the same in the new style. The only time you will need to modify them is when there is some ambiguity as to which parameter is which (usually due to whitespace), or when you need to use the output of a tag as the attribute parameter for another tag.
TIP: This will not work in the new style as it did in the old:
[page scan se=[scratch somevar]]
To get the output of the [scratch somevar]
interpreted, you must place it within a named and quoted attribute:
[page href=scan arg="se=[scratch somevar]"]
What is done with the results of the tag depends on whether it is a
container or standalone tag.
A container tag is one which has an end tag, i.e. [tag] stuff [/tag]
.
A standalone tag has no end tag, as in [area
href=somepage]. (Note that [page ...] and [order ..] are not container tags.)
A container tag will have its output re-parsed for more MiniVend tags by default. If you wish to inhibit this behavior, you must explicitly set the attribute reparse to 0. (Prior to MiniVend 3.09, reparse did not exist.) Note that you will almost always wish the default action.
With some exceptions ([include], [calc], [currency], and [buttonbar ..] among them) the output of a standalone tag will not be re-interpreted for MiniVend tag constructs. All tags accept the INTERPOLATE=1 tag modifier, which causes the interpretation to take place. It is frequent that you will not want to interpret the contents of a [set variable] TAGS [/set] pair, as that might contain tags which should only be upon evaluating an order profile, search profile, or mv_click operation. If you wish to perform the evaluation at the time a variable is set, you would use [set name=variable interpolate=1] TAGS [/set].
To use the new syntax only on a particular page, place one [new]
tag in your page. Likewise, to use old syntax when new is the default,
place one [old]
tag in the page.
If you have regions of the page which work under the old style and fail with the new style, you can surround them with [compat] [/compat] tag pair. This will evaluate that region only with the old style repeated interpolation.
NOTE WHEN USING THE OLD TAG PARSER (NewTags No) or [compat][/compat]: MiniVend in old mode interpolates tags in a highly ordered fashion, with each tag having a precedence. The order of the tag interpolation can be changed by enclosing the tag in a set of double square brackets, bringing it forward in the process. The order of interpolation is:
tag [[ANY TAG]] cart item-list loop default value scratch calc if lookup set data msql|sql file finish_order frames_on frames_off framebase body help buttonbar random rotate checked selected accessories field pagetarget area areatarget page last_page perl order nitems discount subtotal shipping shipping_description salestax total_cost price currency description row process_order process_search process_target
named: [accessories code=``code'' arg=``attribute*, type*, field*, database*, name*, outboard*'']
positional: [accessories code attribute*, type*, field*, database*, name*, outboard*]
If not given one of the optional arguments, expands into the value of the accessories database entry for the product identified by code as found in the products database.
If passed any of the optional arguments, initiates special processing of item attributes based on entries in the product database.
See Item Attributes for a complete description of the arguments.
When called with an attribute, the database is consulted and looks for a comma-separated list of attribute options. They take the form:
name=Label Text, name=Label Text*
The label text is optional -- if none is given, the name will be used.
If an asterisk is the last character of the label text, the item is the default selection. If no default is specified, the first will be the default. An example:
[accessories TK112 color]
This will search the product database for a field named ``color''. If an entry ``beige=Almond, gold=Harvest Gold, White*, green=Avocado'' is found, a select box like this will be built:
<SELECT NAME="mv_order_color"> <OPTION VALUE="beige">Almond <OPTION VALUE="gold">Harvest Gold <OPTION SELECTED>White <OPTION VALUE="green">Avocado </SELECT>
In combination with the mv_order_item and mv_order_quantity variables this can be used to allow entry of an attribute at time of order.
named: [area href=``dir/page'' secure=1* arg=``argument''* form=``form string''*]
positional: [area pg arg*]
HTML example: <A MV=``area dir/page'' HREF=``dir/page.html''>
Produces the
URL to call a MiniVend page, without the surrounding
A
HREF notation. This can be used to get control of your
HREF items, perhaps to place an
ALT string or a Javascript construct. It was originally named
area
because it also can be used in a client-side image map.
<A HREF="[area catalog]" ALT="Main catalog page">
The optional arg is used just as in the page tag.
The optional form
argument allows you to encode a form in the link.
<A HREF="[area form=" mv_order_item=99-102 mv_order_size=L mv_order_quantity=1 mv_separate_items=1 mv_todo=refresh" ]"> Order t-shirt in Large size </A>
The two form values mv_session_id and mv_arg are automatically added when appropriate. (mv_arg is the arg
parameter for the tag.)
If the parameter href
is not supplied, process is used, causing normal MiniVend form processing.
This would generate a form that ordered item number 99-102 on a separate
line (mv_separate_items
being set), with size L
, in quantity 2. Since the page is not set, you will go to the default
shopping cart page -- equally you could set mv_orderpage=yourpage
to go to yourpage
.
You must have TolerateGet set (which is the default) and all normal MiniVend form caveats apply -- you must have an action, you must supply a page if you don't want to go to the default, etc.
You can theoretically submit any form with this, though none of the included values can have newlines or trailing whitespace. If you want to do something like that you will have to write a UserTag.
named: [areatarget href=``dir/page'' target=``frame'' arg=``argument'']
positional: [areatarget pg frame arg*]
Inserts a Vend URL in a format to provide a targeted reference for a client-side imagemap. You set up the <AREA> tag with:
<AREA COORDS="220,0,270,20" HREF="[areatarget page frame]">
If frames are enabled, this will expand to:
<AREA COORDS="220,0,270,20" HREF="http://machine.company.com/vlink/page?ErTxVV8l;;38" TARGET="frame">
If frames are not enabled, this will expand to:
<AREA COORDS="220,0,270,20" HREF="http://machine.company.com/vlink/page?ErTxVV8l;;38">
named: [body type=``n'' extra=``ATTRIBUTE'']
positional: [body n extra*]
Selects from the predefined color schemes and/or backgrounds, and just
becomes a <
BODY> tag if none are defined. The extra
parameter is always appended. See CONTROLLING PAGE APPEARANCE.
named: [buttonbar type=``n'']
positional: [buttonbar n]
AUTOINTERPOLATE: Yes, can be turned off with INTERPOLATE=0
Selects from the predefined buttonbars, and is stripped if it doesn't exist. See CONTROLLING PAGE APPEARANCE. This is somewhat superceded by Variable and [include filename].
syntax: [calc] EXPRESSION [/calc]
AUTOINTERPOLATE: Yes, can be turned off with INTERPOLATE=0
Starts a region where the arguments are calculated according to normal arithmetic symbols. For instance:
[calc] 2 + 2 [/calc]
will display:
4
The [calc] tag is really the same as the [perl] tag, except that it doesn't accept arguments, is more efficient to parse, and is interpolated at a higher precedence.
TIP: The [calc] tag will remember variable values inside one page, so you can do the equivalent of a memory store and memory recall for a loop.
named: [cart name=``name'']
positional: [cart name]
Sets the name of the current shopping cart for display of shipping, price, total, subtotal, and nitems tags. If you wish to use a different price for the cart, all of the above except [shipping] will reflect the normal price field. You must emulate those operations with embedded Perl or the [item-list], [calc], and [currency] tags, or use the PriceAdjustment feature to set it.
named: [checked name=``var_name'' value=``value'']
positional: [checked var_name value]
You can provide a ``memory'' for drop-down menus, radio buttons, and checkboxes with the [checked] and [selected] tags.
This will output
CHECKED if the variable var_name
is equal to
value. Not case sensitive.
syntax: [comment] code [/comment]
Comments out MiniVend tags (and anything else) from a page. The contents are not displayed unless DisplayComments is set in minivend.cfg. Can be nested.
named: [currency convert=1*] number [/currency]
positonal: [currency convert*]
AUTOINTERPOLATE: Yes, can be turned off with INTERPOLATE=0
When passed a value of a single number, formats it according to the currency specification. For instance:
[currency]4[/currency]
will display:
4.00
Uses the Locale and PriceCommas settings as appropriate, and can contain a [calc] region. If the optional
``convert'' parameter is set, it will convert according to PriceDivide>
for the current locale. If Locale is set to fr_FR
, and PriceDivide for fr_FR
is 0.167, the following sequence
[currency convert=1] [calc] 500.00 + 1000.00 [/calc] [/currency]
will cause the number 8.982,04 to be displayed.
named: [data base=``database'' field=``field'' key=``key'' value=``value'' op=``increment] )
positional: [data area field key ``value''* increment*]
HTML example: <PARAM MV=data MV.TABLE=database MV.COL=field MV.ROW=key>
Returns the value of the field in any of the arbitrary databases, or from the variable namespaces. If the optional value is supplied, the database value will be changed to it -- no ] characters may be present in the value unless using the new tag style. If the option increment* is present, the field will be atomically incremented with the value in value.
If a DBM-based database is to be modified, it must be flagged writable on
the page calling the write tag. Use [tag flag write]products[/tag] to mark
the products
database writable, for example.
In addition, the [data ...] tag can access a number of elements in the MiniVend session database:
accesses Accesses within the last 30 seconds arg The argument passed in a [page ...] or [area ...] tag browser The user browser string host MiniVend's idea of the host (modified by DomainTail) last_error The last error from the error logging last_url The current MiniVend path_info logged_in Whether the user is logged in (add-on UserDB feature) pageCount Number of unique URLs generated prev_url The previous path_info referer HTTP_REFERER string ship_message The last error messages from shipping source Source of original entry to MiniVend time Time (seconds since Jan 1, 1970) of last access user The REMOTE_USER string username User name logged in as (add-on UserDB feature)
Databases will hide variables, so don't name a database ``session'', ``scratch'', or any of the other reserved names or you won't be able to use the [data ...] tag to read them. Case is sensitive, so in a pinch you could call the database ``Session'', but it would be better not to.
named: [default name=``variable'' default=``default value'' set=1*]
positional: [default variable value*]
HTML example: <PARAM MV=``default'' MV.NAME=variable MV.DEFAULT=``default'' MV. set=1>
Returns the value of the user form variable variable
if it is non-empty. Otherwise returns default
, which is the string ``default'' if there is no default supplied. Got
that?
If the flag set
is present and non-zero, then the variable will be set to the default
and no value returned to the page. This allows you to initialize things like country, shipping mode, and
other values on a checkout page.
named: [description code=``code'' base=``database'']
positonal: [description code database*]
Expands into the description of the product identified by code as found in the products database. If there is more than one products file defined, they will be searched in order unless constrained by the optional argument base.
named: [discount code=key]
positional: [discount code]
Product discounts can be set upon display of any page. The discounts apply only to the customer receiving them, and are of one of three types:
1. A discount for one particular item code (code/key is the item-code) 2. A discount applying to all item codes (code/key is ALL_ITEMS) 3. A discount applied after all items are totaled (code/key is ENTIRE_ORDER)
The discounts are specified via a formula. The formula is scanned for the
variables $q
and $s, which are substituted for with the item
quantity and subtotal respectively. In the case of the item and all items discount, the formula
must evaluate to a new subtotal for all items of that code that are ordered. The discount for the entire order is applied to the
entire order, and would normally be a monetary amount to subtract or a flat
percentage discount.
Discounts are applied to the effective price of the product, including any quantity discounts.
To apply a straight 20% discount to all items:
[discount ALL_ITEMS] $s * .8 [/discount]
or with named attributes:
[discount code=ALL_ITEMS] $s * .8 [/discount]
To take 25% off of only item 00-342:
[discount 00-342] $s * .75 [/discount]
To subtract $5.00 from the customer's order:
[discount ENTIRE_ORDER] $s - 5 [/discount]
To reset a discount, set it to the empty string:
[discount ALL_ITEMS][/discount]
Perl code can be used to apply the discounts. Here is an example of a discount for item code 00-343 which prices the second one ordered at 1 cent:
[discount 00-343] return $s if $q == 1; my $p = $s/$q; my $t = ($q - 1) * $p; $t .= 0.01; return $t; [/discount]
If you want to display the discount amount, use the [item-discount] tag.
[item-list] Discount for [item-code]: [item-discount] [/item-list]
Finally, if you want to display the discounted subtotal, you need to use the [calc] capability:
[item-list] Discounted subtotal for [item-code]: [currency][calc] [item-price] * [item-quantity] [/calc][/currency] [/item-list]
named: [field code=``code'' name=``fieldname'']
positional: [field name code]
HTML example: <PARAM MV=field MV.COL=column MV.ROW=key>
Expands into the value of the field name for the product identified by code as found by searching the products database. It will return the first entry found in the series of Product Files. the products database. If you want to constrain it to a particular database, use the [data base name code] tag.
named: [file name=``name'' type=``dos|mac|unix''*]
positional: [file name]
Inserts the contents of the named file. The file should normally be relative to the catalog directory -- file names beginning with / or .. are only allowed if the MiniVend server administrator has disabled NoAbsolute.
The optional type parameter will do an appropriate ASCII translation on the file before it is sent.
named: [fly-list code=``product_code'' base=``table''] ... [/fly-list]
``NewTags Yes'' mode only.
Defines an area in a random page which performs the flypage lookup function, implementing the tags below.
[fly-list code="[data session arg]"] (contents of flypage.html) [/fly-list]
If you place the above around the contents of the demo flypage, in a file
named flypage2.html
, it will make these two calls display identical pages:
[page 00-0011] One way to display the Mona Lisa [/page] [page flypage2 00-0011] Another way to display the Mona Lisa [/page]
named: [framebase name]
Outputs a <BASE FRAME=``name''> tag only if MiniVend is in frames mode. It should be used within the HTML <HEAD> section.
named: [frames_off]
Turns off the frames processing option. This can be used to disable frames, perhaps as a clickable option for users. It is persistent for the entire session, or until counteracted with a [frames_on] tag.
IMPORTANT NOTE: This doesn't turn of frames in your browser! If you let a TARGET tag escape, it will probably cause a new window to be opened, or other types of anomalous operation.
named: [frames_on]
Turns on the frames processing option, which is disabled by default. The proper way to use this is to put it ONLY in the first page which is loaded by frame-based browsers, as part of the initial frame load. It is persistent for the entire session, or until counteracted with a [frames_off] tag.
named: [if type=``type'' term=``field'' op=``op'' compare=``compare'']
positional: [if type field op* compare*]
negated: [if type=``!type'' term=``field'' op=``op'' compare=``compare'']
positional: [if !type field op* compare*]
Allows conditional building of HTML based on the setting of various MiniVend session and database values. The general form is:
[if type term op compare] [then] If true, this is printed on the document. The [then] [/then] is optional in most cases. If ! is prepended to the type setting, the sense is reversed and this will be output for a false condition. [/then] [elsif type term op compare] Optional, tested when if fails [/elsif] [else] Optional, printed when all above fail [/else] [/if]
The [if]
tag can also have some variants:
[if explicit][condition] CODE [/condition] Displayed if valid Perl CODE returns a true value. [/if]
You can do some Perl-style regular expressions:
[if value name =~ /^mike/] This is the if with Mike. [elsif value name =~ /^sally/] This is an elsif with Sally. [/elsif] [elsif value name =~ /^pat/] This is an elsif with Pat. [/elsif] [else] This is the else, no name I know. [/else] [/if]
While the new tag syntax works for [if ...]
, it is more convenient to use the old in most cases. It will work fine
with both parsers. The only exception is if you are planning on doing a
test on the results of another tag sequence: [if value name =~ /[value
b_name]/] Shipping name matches billing name. [/if]
Oops! This will not work with the new parser. You must do instead
[compat] [if value name =~ /[value b_name]/] Shipping name matches billing name. [/if] [/compat]
or
[if type=value term=name op="=~" compare="/[value b_name]/"] Shipping name matches billing name. [/if]
The latter has the advantage of working with any tag:
[if type=value term=high_water op="<" compare="[shipping]"] Shipping cost is too high, charter a truck. [/if]
If you wish to do
AND and
OR operations, you will have to use
[if explicit]
. This allows complex testing and parsing of values.
There are many test targets available:
[if config CreditCardAuto] Auto credit card validation is enabled. [/if]
[if data products::size::99-102] There is size information. [else] No size information. [/else] [/if]
[if data products::size::99-102 =~ /small/i] There is a small size available. [else] No small size available. [/else] [/if]
[if discount 99-102] Item is discounted. [/if]
[if explicit] [condition] $country = '[value country]'; return 1 if $country =~ /u\.?s\.?a?/i; return 0; [/condition] You have indicated a US address. [else] You have indicated a non-US address. [/else] [/if]
This example is a bit contrived, as the same thing could be accomplished with [if value country =~ /u\.?s\.?a?/i], but you will run into many situations where it is useful.
This will work for Variable values:
[if explicit "__MYVAR__"] .. [/if]
[if file /home/user/www/images/[item-code].gif] <IMG SRC="[item-code].gif"> [/if]
The file test requires that the SafeUntrap directive contains
ftfile
(which is the default).
[if items]You have items in your shopping cart.[/if] [if items layaway]You have items on layaway.[/if]
[if ordered 99-102] ... [/if] Checks the status of an item on order, true if item 99-102 is in the main cart.
[if ordered 99-102 layaway] ... [/if] Checks the status of an item on order, true if item 99-102 is in the layaway cart.
[if ordered 99-102 main size] ... [/if] Checks the status of an item on order in the main cart, true if it has a size attribute.
[if ordered 99-102 main size =~ /large/i] ... [/if] Checks the status of an item on order in the main cart, true if it has a size attribute containing 'large'. THE CART NAME IS REQUIRED IN THE OLD SYNTAX. The new syntax for that one would be:
[if type=ordered term="99-102" compare="size =~ /large/i"]
To make sure it is exactly large, you could use:
[if ordered 99-102 main size eq 'large'] ... [/if]
[if ordered 99-102 main lines] ... [/if] Special case -- counts the lines that the item code is present on. (Only useful, of course, when mv_separate_items or SeparateItems is defined.)
[if salestax [value state] > 0] There is salestax for your state. [else] No salestax for your state. [/else] [/if]
Key matching is case-insensitive.
[if scratch mv_separate_items] Ordered items will be placed on a separate line. [else] Ordered items will be placed on the same line. [/else] [/if]
mv_
are MiniVend special values, and should be tested/used with caution.
The field term is the specifier for that area. For example, [if session frames] would return true if the frames session parameter was set.
As an example, consider buttonbars for frame-based setups. It would be nice to display a different buttonbar (with no frame targets) for sessions that are not using frames:
[if session frames] [buttonbar 1] [else] [buttonbar 2] [/else] [/if]
Another example might be the when search matches are displayed. If you use the string '[value mv_match_count] titles found', it will display a plural for only one match. Use:
[if value mv_match_count != 1] [value mv_match_count] matches found. [else] Only one match was found. [/else] [/if]
The op term is the compare operation to be used. Compare operations are as in Perl:
== numeric equivalence eq string equivalence > numeric greater-than gt string greater-than < numeric less-than lt string less-than != numeric non-equivalence ne string equivalence
Any simple perl test can be used, including some limited regex matching.
More complex tests are best done with [if explicit]
.
Additional conditions for test, applied if the initial [if ..]
test fails.
Named attributes:
[import table=table_name type=(TAB|PIPE|CSV|%%|LINE) continue=(NOTES|UNIX|DITTO) separator=c]
Import one or more records into a database. The type is any of the valid MiniVend delimiter types, with the default being defined by the setting of Delimiter. The table must already be a defined MiniVend database table; it cannot be created on the fly. (If you need that, it is time to use SQL.)
The type of LINE
and continue
setting of NOTES
is particularly useful, for it allows you to name your fields and not have
to remember the order in which they appear in the database. The following
two imports are identical in effect:
[import table=orders] code: [value mv_order_number] shipping_mode: [shipping-description] status: pending [/import] [import table=orders] shipping_mode: [shipping-description] status: pending code: [value mv_order_number] [/import]
The code or key must always be present, and is always named code.
If you do not use NOTES
mode, you must import the fields in the same order as they appear in the
ASCII source file.
The [import ....] TEXT [/import]
region may contain multiple records. If using NOTES
mode, you must use a separator, which by default is a form-feed character
(^L).
named: [include file=``name'']
positional: [include file]
AUTOINTERPOLATE: ALWAYS -- even Variable settings are interpolated.
NOTE: New to MiniVend 3.04.
Same as [file name]
except interpolates for all MiniVend tags and variables.
named: [item-accessories attribute*, type*, field*, database*, name*, outboard*]
MiniVend allows item attributes to be set for each ordered item. This allows a size, color, or other modifier to be attached to a common part number. If multiple attributes are set, then they should be separated by commas. Previous attribute values can be saved by means of a hidden field on a form, and multiple attributes for each item can be stacked on top of each other.
The configuration file directive UseModifier is used to set the name of the modifier or modifiers. For example
UseModifier size,color
will attach both a size and color attribute to each item code that is ordered.
IMPORTANT NOTE: You may not use the following names for attributes:
item group quantity code mv_ib mv_mi mv_si
You can also set it in scratch with the mv_UseModifier scratch variable --
[set mv_UseModifier]size color[/set] has the same effect as above. This
allows multiple options to be set for products. Whichever one is in effect
at order time will be used. Be careful, you cannot set it more than once on
the same page. Setting the mv_separate_items or global directive SeparateItems
places each ordered item on a separate line, simplifying attribute
handling. The scratch setting for mv_separate_items
has the same effect.
The modifier value is accessed in the [item-list] loop with the [item-modifier attribute] tag, and form input fields are placed with the [modifier-name attribute] tag. This is similar to the way that quantity is handled, except that attributes can be ``stacked'' by setting multiple values in an input form.
You cannot define a modifier name of code or quantity, as they are already used. You must be sure that no fields in your forms have digits appended to their names if the variable is the same name as the attribute name you select, as the [modifier-name size] variables will be placed in the user session as the form variables size0, size1, size2, etc.
You can use the [loop item,item,item] list to reference multiple display or selection fields for modifiers (in MiniVend 3.0, you can have it automatically generated --see below). The modifier value can then be used to select data from an arbitrary database for attribute selection and display.
Below is a fragment from a shopping basket display form which shows a selectable size with ``sticky'' setting. Note that this would always be contained within the [item_list] [/item-list] pair.
<SELECT NAME="[modifier-name size]"> <OPTION [selected [modifier-name size] S]> S <OPTION [selected [modifier-name size] M]> M <OPTION [selected [modifier-name size] L]> L <OPTION [selected [modifier-name size] XL]> XL </SELECT>
It could just as easily be done with a radio button group combined with the [checked ...] tag.
MiniVend 3.0 will automatically generate the above select box when the [accessories <code> size] or [item-accessories size] tags are called. They have the syntax:
[item_accessories attribute*, type*, field*, database*, name*, outboard*] [accessories code attribute*, type*, field*, database*, name*, outboard*]
The item attribute as specified in the UseModifier configuration directive.
Typical are size
or color
.
select Builds a dropdown <SELECT> menu for the attribute. NOTE: This is the default. multiple Builds a multiple dropdown <SELECT> menu for the attribute. The size is equal to the number of option choices. display Shows the label text for *only the selected option*. show Shows the option choices (no labels) for the option. radio Builds a radio box group for the item, with spaces separating the elements. radio nbsp Builds a radio box group for the item, with separating the elements. radio left n Builds a radio box group for the item, inside a table, with the checkbox on the left side. If "n" is present and is a digit from 2 to 9, it will align the options in that many columns. radio right n Builds a radio box group for the item, inside a table, with the checkbox on the right side. If "n" is present and is a digit from 2 to 9, it will align the options in that many columns.
check Builds a checkbox group for the item, with spaces separating the elements. check nbsp Builds a checkbox group for the item, with separating the elements. check left n Builds a checkbox group for the item, inside a table, with the checkbox on the left side. If "n" is present and is a digit from 2 to 9, it will align the options in that many columns. check right n Builds a checkbox group for the item, inside a table, with the checkbox on the right side. If "n" is present and is a digit from 2 to 9, it will align the options in that many columns.
The default is 'select', which builds an HTML select form entry for the attribute. Also recognized is 'multiple', which generates a multiple-selection drop down list, 'show', which shows the list of possible attributes, and 'display', which shows the label text for the selected option only.
When called with an attribute, the database is consulted and looks for a comma-separated list of attribute options. They take the form:
name=Label Text, name=Label Text*
The label text is optional -- if none is given, the name will be used.
If an asterisk is the last character of the label text, the item is the default selection. If no default is specified, the first will be the default. An example:
[item_accessories color]
This will search the product database for a field named ``color''. If an entry ``beige=Almond, gold=Harvest Gold, White*, green=Avocado'' is found, a select box like this will be built:
<SELECT NAME="mv_order_color"> <OPTION VALUE="beige">Almond <OPTION VALUE="gold">Harvest Gold <OPTION SELECTED>White <OPTION VALUE="green">Avocado </SELECT>
In combination with the mv_order_item and mv_order_quantity variables this can be used to allow entry of an attribute at time of order.
If used in an item list, and the user has changed the value, the generated select box will automatically retain the current value the user has selected.
The value can then be displayed with [item-modifier size] on the order report, order receipt, or any other page containing an [item_list].
named: [item-list name=``cart'']
positional: [item-list cart*]
Within any page, the [item_list cart*] element shows a list of all the items ordered by the customer so far. It works by repeating the source between [item_list] and [/item_list] once for each item ordered.
NOTE: The special tags that reference item within the list are not normal MiniVend tags, do not take named attributes, and cannot be contained in an HTML tag (other than to substitute for one of its values or provide a conditional container). They are interpreted only inside their corresponding list container. Normal MiniVend tags can be interspersed, though they will be interpreted after all of the list-specific tags.
Between the item_list markers the following elements will return information for the current item:
column
in table table is non-blank, the following text up to the [/if_data] tag is substituted. This can be used to substitute
IMG or other tags only if the corresponding source item is present. Also accepts a [else]else text[/else] pair for the opposite condition.
[item-last][calc] return -1 if '[item-field weight]' eq ''; return 1 if '[item-field weight]' < 1; return 0; [/calc][/item-last]
If this is contained in your [item-list]
(or [search-list]
or flypage) and the weight field is empty, then a numerical -1
will be output from the [calc][/calc] tags; the list will end and the item
will not be shown. If the product's weight field is less than 1, a numerical 1 is
output. The item will be shown, but will be the last item shown. (If it is
an [item-list]
, any price for the item will still be added to the subtotal.)
NOTE: no
HTML style.
attribute
for the current item.
[item-next][calc][item-field weight] < 1[/calc][/item-next]
If this is contained in your [item-list]
(or [search-list]
or flypage) and the product's weight field is less than 1, then a numerical 1
will be output from the [calc][/calc] operation. The item will not be
shown. (If it is an [item-list]
, any price for the item will still be added to the subtotal.)
n
(from the products file) of the current item, with currency formatting. If
the optional ``noformat'' is set, then currency formatting will not be
applied.
n
(from the products file) of the current item, with currency formatting. If
the optional ``noformat'' is set, then currency formatting will not be
applied. Returns regular price if not discounted.
named: [lookup table=``database'' col=``column'' key=row value=``[value name]'']
positional: [lookup table column row ``a quoted value'']
This is essentially same as the following:
[if value name] [then][value name][/then] [else][data database column row][/else] [/if]
named: [loop with=``-a''* arg=``item item item'' search=``se=whatever'']
positional: [loop item item item] LIST [/loop]
HTML example:
<TABLE><TR MV="loop 1 2 3"><TD>[loop-code]</TD></TR></TABLE>
Returns a string consisting of the LIST, repeated for every item in a comma-separated or space-separated list. Operates in the same fashion as the [item-list] tag, except for order-item-specific values. Intended to pull multiple attributes from an item modifier -- but can be useful for other things, like building a pre-ordained product list on a page.
Loop lists can be nested reliably in MiniVend 3.06 by using the with=``tag'' parameter. New syntax:
[loop arg="A B C"] [loop with="-a" arg="[loop-code]1 [loop-code]2 [loop-code]3"] [loop with="-b" arg="X Y Z"] [loop-code-a]-[loop-code-b] [/loop] [/loop] [/loop]
An example in the old syntax:
[compat] [loop 1 2 3] [loop-a 1 2 3 ] [loop-b 1 2 3] [loop-code].[loop-code-a].[loop-code-b] [/loop-b] [/loop-a] [/loop] [/compat]
All loop items in the inner loop-a loop need to have the with
value appended, i.e. [loop-field-a name]
, [loop-price-a]
, etc. Nesting is arbitrarily large, though it will be slow for many
levels.
You can do an arbitrary search with the search=``args'' parameter, just as in a one-click search:
[loop search="se=Americana/sf=category"] [loop-code] [loop-field title] [/loop]
The above will show all items with a category containing the whole world ``Americana'', and will work the same in both old and new syntax.
table
is non-empty, and the
ELSE (if any) otherwise.
products
table is non-empty, and the ELSE (if any) otherwise.
[loop-last][calc] return -1 if '[loop-field weight]' eq ''; return 1 if '[loop-field weight]' < 1; return 0; [/calc][/loop-last]
If this is contained in your [loop list]
and the weight field is empty, then a numerical -1
will be output from the [calc][/calc] tags; the list will end and the item
will not be shown. If the product's weight field is less than 1, a numerical 1 is
output. The item will be shown, but will be the last item shown.
[loop-next][calc][loop-field weight] < 1[/calc][/loop-next]
If this is contained in your [loop list]
and the product's weight field is less than 1, then a numerical 1
will be output from the [calc][/calc] operation. The item will not be
shown.
named: [nitems cart*]
Expands into the total number of items ordered so far. Takes an optional cart name as a parameter.
named: [order code=``code'' href=``cart/page'' base=``database'']
positional: [order code cart/page* database*]
HTML example: <A MV=``order code'' HREF=``ord/basket''>
Expands into a hypertext link which will include the specified code in the
list of products to order and display the order page. code
should be a product code listed in one of the ``products'' databases. The
optional argument cart/page selects the shopping cart the item will be placed in (begin with / to use
the default cart main
) and the order page that will display the order. The optional argument database constrains the order to a particular products file -- if not specified, all
databases defined as products files will be searched in sequence for the
item.
Example:
Order a [order TK112]Toaster[/order] today.
named: [/order]
Expands into </a>. Used with the order element, such as: Buy a [order TK112]Toaster[/order] today.
named: [page href=``dir/page'' arg=``argument''* secure=1* form=``form string''*]
positional: [page dir/page arg*] (only two positional parameters)
HTML example: <A MV=``page'' MV.HREF=``dir/page'' MV.ARG=``arg'' HREF=``dir/page.html''>
Insert a hyperlink to the specified catalog page pg. For example, [page shirts] will expand into < a href=``http://machine.company.com/cgi-bin/vlink/shirts?WehUkATn;;1''>. The catalog page displayed will come from ``shirts.html'' in the pages directory.
The additional argument will be passed to MiniVend and placed in the {arg}
session parameter. This allows programming of a conditional page display
based on where the link came from. The argument is then available with the
tag [data session arg], or the embedded Perl session variable
$Safe{'session'}->{arg}. If you set the catalog configuration option
NewEscape, which is the default, then spaces and some other characters will be
escaped with the %NN
HTTP-style notation and unescaped when
the argument is read back into the session.
A bit of magic occurs if MiniVend has built a static plain HTML page for the target page. Instead of generating a normal MiniVend-parsed page reference, a static page reference will be inserted if the user has accepted and sent back a cookie with the session ID.
The optional form
argument allows you to encode a form in the link.
[page form=" mv_order_item=99-102 mv_order_size=L mv_order_quantity=1 mv_separate_items=1 mv_todo=refresh"] Order t-shirt in Large size </A>
The two form values mv_session_id and mv_arg are automatically added when appropriate. (mv_arg is the arg
parameter for the tag.)
If the parameter href
is not supplied, process is used, causing normal MiniVend form processing. If the href
points to an http:// link no MiniVend
URL processing will be done, but the mv_session_id
This would generate a form that ordered item number 99-102 on a separate
line (mv_separate_items
being set), with size L
, in quantity 2. Since the page is not set, you will go to the default
shopping cart page -- equally you could set mv_orderpage=yourpage
to go to yourpage
.
You must have TolerateGet set (which is the default) and all normal MiniVend form caveats apply -- you must have an action, you must supply a page if you don't want to go to the default, etc.
You can theoretically submit any form with this, though none of the included values can have newlines or trailing whitespace. If you want to do something like that you will have to write a UserTag.
named: [pagetarget href=``dir/page'' target=``frame'' arg=``argument'']
positional: [pagetarget pg frame arg*]
Same as the page element above, except it specifies an output frame to
target if frames are turned on. The name is case-sensitive, and if it doesn't exist a new window will be popped up.
This is the same as the [page ...] tag if frames are not activated. For
example, [pagetarget shirts main] will expand into a link like <a href=``http://machine.company.com/cgi-bin/vlink/shirts?WehUkATn;;1''
TARGET=``main''>. The catalog page displayed will come from shirts.html
in the pages directory, and be output to the main
frame. Be careful, frame names are case-sensitive.
MiniVend allows you to pass a search in a
URL. Just specify the search with the special page
reference scan
. Here is an example:
[page scan se=Impressionists sf=category] Impressionist Paintings [/page]
Here is the same thing from a home page (assuming /cgi-bin/vlink is the CGI path for MiniVend's vlink):
<A HREF="/cgi-bin/vlink/scan/se=Impressionists/sf=category"> Impressionist Paintings </A>
The two-letter abbreviations are mapped with these letters:
DL mv_raw_dict_look MM mv_more_matches SE mv_raw_searchspec ac mv_all_chars bd mv_base_directory bs mv_begin_string co mv_coordinate cs mv_case de mv_dict_end df mv_dict_fold di mv_dict_limit dl mv_dict_look do mv_dict_order dp mv_delay_page dr mv_record_delim em mv_exact_match er mv_spelling_errors fi mv_search_file fm mv_first_match fn mv_field_names hs mv_head_skip id mv_index_delim lr mv_line_return ml mv_matchlimit mm mv_max_matches mp mv_profile ms mv_min_string ne mv_negate nu mv_numeric op mv_column_op os mv_orsearch ra mv_return_all rd mv_return_delim rf mv_return_fields rg mv_range_alpha rl mv_range_look rm mv_range_min rn mv_return_file_name rs mv_return_spec rx mv_range_max se mv_searchspec sf mv_search_field sp mv_search_page sq mv_sql_query st mv_searchtype su mv_substring_match tc mv_sort_command tf mv_sort_field to mv_sort_option ty mv_sort_crippled
They can be treated just the same as form variables on the page, except that they can't contain spaces, '/' in a file name, or quote marks. These characters can be used in
URL hex encoding, i.e. %20
is a space, %2F
is a
/
, etc. -- &sp;
or  
will not be recognized. If you use one of the methods below to escape these
``unsafe'' characters, you won't have to worry about this.
Beginning in MiniVend 3.08, you may specify a one-click search in three different ways. The first is as used in previous versions, with the scan
URL being specified completely as the page name. The second two use the ``argument'' parameter to the
[page ...]
or [area ...]
tags to specify the search (an argument to a scan is never valid anyway).
[page scan se=Surreal/se=Gogh/os=yes/su=yes/sf=artist/sf=category] Van Gogh -- compare to surrealists [/page]
In this method of specification, to replace a / (slash) in a file name (for the sp, bd, or fi parameter) you must use the shorthand of ::, i.e. sp=results::standard. (This may not work for some browsers, so you should probably either put the page in the main pages directory or define the page in a search profile.)
[page scan se="Van Gogh"&sp=lists/surreal&os=yes&su=yes&sf=artist&sf=category] Van Gogh -- compare to surrealists [/page]
Any ``unsafe'' characters will be escaped.
[page scan se="Van Gogh" sp=lists/surreal os=yes su=yes sf=artist sf=category ] Van Gogh -- compare to surrealists [/page]
Any ``unsafe'' characters will be escaped. You may not search for trailing spaces in this method; it is allowed in the other notations.
New syntax and old syntax handle the tags the same, though if by some odd
chance you wanted to be able to search for a ]
(right square bracket) you would need to use new syntax.
The optional arg is used just as in the page tag.
named: [/page]
Expands into </a>. Used with the page element, such as:
[page shirts]Our shirt collection[/page].
TIP: A small efficiency boost in large pages is to just use the </A> tag.
named: [perl args=``arg1 arg2 ... argn'' interpolate=1*] CODE [/perl]
positional: [perl args] code [/perl]
HTML example:
<PRE mv=perl mv.arg="values browser"> $name = $Safe{'values'}{'name'}; $name = $Safe{'browser'}; return "Hi, $name! How do you like your $browser? </PRE>
Perl code can be directly embedded in MiniVend pages. The code is specified as [perl arguments*] any_legal_perl_code [/perl]. The value returned by the code will be inserted on the page.
Using MiniVend variables with embedded Perl capability is not recommended unless you are thoroughly familiar with Perl 5 references. You can insert Minivend tags inside the Perl code, though when using the new syntax, you will need to pass an INTERPOLATE=1 parameter to have tags inside [perl] and [/perl] interpreted. (In the old syntax, most tags are evaluated before [perl], though there are exceptions.)
More often you will want to use the tag access routine &safe_tag, which takes the tag name and any arguments as parameters. This has the advantage of only performing the operation when the code is executed. (A few tags can't be used with safe_tag, notably ones accessing a database that has not previously been accessed on the page.)
Examples:
# Simple example, old syntax [perl] $comments = '[value comments]'; [/perl]
# New syntax # If the item might contain a single quote [perl interpolate=1] $comments = '[value comments escaped]'; [/perl]
# Another method to avoid escape problems $comments = q{[value comments]};
# Works with all, only executed if code is reached $comments = safe_tag('value', 'comments');
This allows you to pass user-space variables for most needed operations. You can pass whole lists of items with constructs like:
# Perl ignores the trailing comma my(%prices) = ( [item_list] '[item_code]', '[item-price]', [/item_list]);
Even easier is the definition of a subroutine:
[set Thanks] my($name, $number) = @_; "Thanks, $name, for your order! The order number is $number.\n"; [/set]
# New syntax [perl arg=sub interpolate=1] Thanks ('[value name escaped]', '[value mv_order_number escaped]') [/perl]
# Old syntax, depends on [value ...] interpolated before [perl] [perl sub] Thanks ('[value name escaped]', '[value mv_order_number escaped]') [/perl]
(The escaped
causes any single quotes which might be contained in the values to be
escaped, preventing syntax errors in the case of a name like ``O'Reilly''.)
The arguments that can be passed are any to all of:
# Move contents of 'layaway' cart to main cart $Safe{carts}->{main} = $Safe{carts}->{layaway}; $Safe{carts}->{main} = [];
Careful with this -- you can lose the items on order with improper code, though syntax errors will be caught before the code is run.
# Set if the user had a value for name in the *current* form $name = $Safe{'cgi'}->{name};
# Product code of first item in cart $item_code = $Safe{items}->[0]->{code};
# Quantity for third item in cart $item_code = $Safe{items}->[2]->{quantity};
# Color of second item in cart $item_code = $Safe{items}->[2]->{color};
@_
argument
array.
IMPORTANT NOTE: Global subroutines are not subject to the stringent security checking of the Safe module, so almost anything goes there. The subroutine will be able to modify any variable in MiniVend, and will be able to write to read and write any file that the MiniVend daemon has permission to write. Though this gives great power, it should be used with caution. Careful! They are defined in the main minivend.cfg file, so should be safe from individual users in a multi-catalog system.
Global subroutines are defined in minivend.cfg with the GlobalSub directive, or in user catalogs which have been enabled via AllowGlobal. Global subroutines are much faster than the others as they are pre-compiled. (Faster still are UserTag definitions.)
Catalog subroutines are defined in catalog.cfg, with the Sub directive. They are subject to the stringent Safe.pm security restrictions that are controlled by SafeUntrap. If you wish to have default arguments supplied to them, use the SubArgs directive.
Scratch subroutines are defined in the pages, and are also subject to Safe.pm checking. See the beginning of this section for an example of a subroutine definition. There is no ``sub name { }'' that surrounds it -- the subroutine is named from the name of the scratch variable.
# Read the user's selected shipping mode my $shipmode = $Safe{values}->{mv_shipmode};
The code can be as complex as desired, but cannot use any operators that modify the file system or use ``unsafe'' operations like ``system'', ``exec'', or backticks. These constraints are enforced with the default permissions of the standard Perl module Safe -- operations may be untrapped on a system-wide basis with the SafeUntrap directive.
The result of the tag will be the result of the last expression evaluated, just as in a subroutine. If there is a syntax error or other problem with the code, there will be no output.
Here is a simple one which does the equivalent of the classic hello.pl program:
[perl] my $tmp = "Hello, world!"; $tmp; [/perl]
Of course you wouldn't need to set the variable -- it is just there to show the capability.
To echo the user's browser, but within some HTML tags:
[perl browser] my $html = '<H5>'; $html .= $Safe{'browser'}; $html .= '</H5>'; $html; [/perl]
To show the user their name, and the current time:
[perl values]
my $string = "Hi, " . $Safe{values}->{'name'} ". The time is now "; $string .= localtime; $string;
[/perl]
syntax: [post] DELAYED TAGS [/post]
NOTE: This is ignored if using the new syntax.
Selects an area that will not be interpolated until after the rest of the page is interpolated. If followed by a number, will match a terminating [/post] tag with the corresponding number.
named: [price code=``code'' quantity=``quantity'' base=``database'' noformat=1*]
positional: [price code quantity* database* noformat*]
Expands into the price of the product identified by code as found in the
products database. If there is more than one products file defined, they
will be searched in order unless constrained by the optional argument base. The optional argument quantity selects an entry from the quantity price list. To receive a raw number,
with no currency formatting, use the option noformat=1
.
MiniVend maintains a price in its database for every product. The price field is the one required field in the product database -- it is necessary to build the price routines.
For speed, MiniVend builds the code that is used to determine a product's price at catalog configuration time. If you choose to change a directive that affects product pricing you must reconfigure the catalog.
There are several ways that MiniVend can modify the price of a product during normal catalog operation. Several of them require that the pricing.asc file be present, and that you define a pricing database. You do that by placing the following directive in catalog.cfg:
Database pricing pricing.asc 1
Configurable directives and tags with regard to pricing:
price
in the pricing database. The price field contains a space-separated list of prices that correspond to the
quantity levels defined in the
PriceBreaks directive. If quantity is to be applied to all items in the shopping cart
(as opposed to quantity of just that item) then the
MixMatch directive should be set to Yes.
For example, if you decided to adjust the price of T-shirt part number 99-102 up 1.00 when the size is extra large and down 1.00 when the size is small, you would have the following directives defined in <catalog.cfg>:
Database pricing pricing.asc 1 UseModifier size PriceAdjustment size
To enable the automatic modifier handling of MiniVend 3.0, you would define a size field in products.asc:
code description price size 99-102 T-Shirt 10.00 S=Small, M=Medium, L=Large*, XL=Extra Large
You would place the proper tag within your [item-list] on the shopping-basket or order page:
[item-accessories size]
In the pricing.asc database source, you would need:
code S XL 99-102 -1.00 1.00
As of MiniVend 3.06, if you want to assign a price based on the option, precede the number with an equals sign:
code S M L XL 99-102 =9.00 =10 =10 =11
IMPORTANT NOTE: Price adjustments occur AFTER quantity price breaks, so the above would negate anything set with the PriceBreaks directive/option.
Numbers that begin with an equals sign (=
) are used as absolute prices and are interpolated for MiniVend tags first, so you can use subroutines to set the price. To facilite coordination
with the subroutine, the session variables item_code
and item_quantity
are set to the code and quantity of the item being evaluated. They would be
accessed in a global subroutine with $Vend::Session-
>{item_code}
and $Vend::Session-
>{item_quantity}
.
The pricing information must always come from a database because of security.
See CommonAdjust for another scheme that makes the same adjustment for any item having the attribute -- both schemes cannot be used at the same time. (This is true even if you were to change the value of $Vend::Cfg->{CommonAdjust} in a subroutine -- the pricing algorithm is built at catalog configuration time.)
AUTOINTERPOLATE: Yes, can be turned off with INTERPOLATE=0
Selects from the predefined random messages, and is stripped if none exist. See CONTROLLING PAGE APPEARANCE in the MiniVend documentation.
named: [rotate floor=``n'' ceiling=``n'']
positional: [rotate ceiling* floor*]
AUTOINTERPOLATE: Yes, can be turned off with INTERPOLATE=0
Selects from the predefined rotating banner messages, and is stripped if
none exist. The optional ceiling
sets the highest number that will be selected -- likewise floor
sets the lowest. The default is to sequence through all defined rotating
banners. Each user has a separate rotation pattern, and each floor/ceiling
combination has a separate rotation value.
named: [row width=``nn''] COLUMN DEFINITIONS [/row]
positional: [row nn] .... [/row]
Formats text in tables. Intended for use in emailed reports or < PRE>< /PRE> HTML areas. The parameter nn gives the number of columns to use. Inside the row tag, [col param=value ...] tags may be used.
The parameters are:
width=nn The column width, I<including the gutter>. Must be supplied, there is no default. A shorthand method is to just supply the number as the I<first> parameter, as in [col 20]. gutter=n The number of spaces used to separate the column (on the right-hand side) from the next. Default is 2. spacing=n The line spacing used for wrapped text. Default is 1, or single-spaced. wrap=(yes|no) Determines whether text that is greater in length than the column width will be wrapped to the next line. Default is I<yes>. align=(L|R|I) Determines whether text is aligned to the left (the default), the right, or in a way that might display an HTML text input field correctly.
named: [salestax cart=cartname* noformat=1*]
old: [salestax cart* noformat*]
mandatory: NONE
optional: cart noformat
Expands into the sales tax on the subtotal of all the items ordered so far
for the cart, default cart is main
. If there is no key field to derive the proper percentage, such as state
or zip code, it is set to 0. If the noformat tag is present and non-zero,
the raw number with no currency formatting will be given.
named: [scratch name]
Returns the contents of a scratch variable to the page.
named: [selected name=``var_name'' value=``value'' multiple=``yes'']
positional: [selected var_name value MULTIPLE*]
You can provide a ``memory'' for drop-down menus, radio buttons, and checkboxes with the [checked] and [selected] tags.
This will output
SELECTED if the variable var_name
is equal to
value. If the optional
MULTIPLE argument is present, it will look for any of
a variety of values. Not case sensitive.
Here is a drop-down menu that remembers an item-modifier color selection:
<SELECT NAME="color"> <OPTION [selected color blue]> Blue <OPTION [selected color green]> Green <OPTION [selected color red]> Red </SELECT>
Here is the same thing, but for a shopping-basket color selection
<SELECT NAME="[modifier-name color]"> <OPTION [selected [modifier-name color] blue]> Blue <OPTION [selected [modifier-name color] green]> Green <OPTION [selected [modifier-name color] red]> Red </SELECT>
named: [set name=``variable''] value [/set]
positional: [set variable]value[/set]
HTML example: <PRE MV=``set variable''> value </PRE>
Sets a scratchpad variable to value.
Most of the mv_* variables that are used for search and order conditionals are in another namespace -- they can be set by means of hidden fields in a form.
You can set an order profile with:
[set checkout] name=required address=required [/set] <INPUT TYPE=hidden NAME=mv_order_profile VALUE="checkout">
A search profile would be set with:
[set substring_case] mv_substring_match=yes mv_case=yes [/set] <INPUT TYPE=hidden NAME=mv_profile VALUE="substring_case">
named: [shipping name=``mode'']
positional: [shipping mode*]
The shipping cost of the items in the basket via mode
-- the default mode is the shipping mode currently selected in the mv_shipmode
variable. See SHIPPING.
named: [shipping_description name=``mode'']
old: [shipping-description mode*]
mandatory: NONE
optional: name is the shipping mode identifier, i.e. upsg
.
The text description of mode -- the default is the shipping mode currently selected.
named: [sql array] SQL [/sql identifier*]
A complete array of arrays, suitable for eval by Perl, can be returned by this query. This tag pair encloses any valid SQL query, and returns the results (if any) as a string representing rows and columns, in Perl array syntax. If placed in an embedded Perl area as:
[perl]
my $string =<<'EOF'; [sql array]select * from arbitrary where code <= '19'[/sql arbitrary]
EOF my $ary = eval $string; my $out = ''; my $i; foreach $i (@$ary) { $out .= $i->[0]; $out .= "<BR>"; } $out;
[/perl]
NOTE: The 'EOF' string terminator must START the line, and not have trailing characters. DOS users, beware of carriage returns!
named: [sql hash] SQL [/sql identifier*]
A complete hash of hashes, suitable for eval by Perl, can be returned by this query. This tag pair encloses any valid SQL query, and returns the results (if any) as a string representing rows and columns, in Perl associative array, or hash, syntax. If placed in an embedded Perl area as:
[perl]
my $string =<<'EOF'; [sql hash]select * from arbitrary where code <= '19'[/sql]
EOF my $hash = eval $string; my $out = ''; my $key; foreach $key (keys %$hash) { $out .= $key->{field1}; $out .= "<BR>"; } $out;
[/perl]
named: [sql html] SQL [/sql]
This tag returns a set of HTML table rows with bold field names at the top, followed by each row in a set of table cells. The <TABLE> and </TABLE> tags are not supplied, so you can set your own border and shading options. Example:
<TABLE BORDER=2> [sql html]select * from arbitrary where code > '19' order by field2[/sql] </TABLE>
named: [sql list SQL] list [/sql]
This tag differs from the rest in that it passes the query enclosed inside the tag itself. The enclosed text is then evaluated with the same method as with a loop list, with data items (in columns) iterated over for the contents of a list. The following snippet will place a three-column list in an HTML table:
<TABLE BORDER=2> <TR><TH><B>SKU</B></TH><TH><B>Description</B></TH><TH><B>Price</B></TH> [sql list select * from arbitrary where code > '19' order by field2 ] <TR> <TD>[page [sql-code]][sql-code]</A></TD> <TD>[sql-param 1]</TD> <TD>[sql-param 2]</TD> </TR> [/sql] </TABLE>
It uses the same tags as in the [loop_list], except prefixed with sql
. Available are the following, in order of interpolation:
[sql_param n] Field n of the returned query (in the row) [if_sql_field fld] Returns enclosed text only product field not empty [/if_sql_field] Terminator for above [if_sql_data db fld] Returns enclosed text only if data field not empty [/if_sql_field] Terminator for above [sql_increment] Returns integer count of row [sql_code] The first field of each row returned [sql_data db fld] Database field for [sql_code] [sql_description] Product description for [sql_code] [sql_field fld] Product field for [sql_code] [sql_link] Same as item-link [sql_price q*] Price for [sql_code], optional quantity q
named: [sql param] SQL [/sql]
A list of keys, or in fact any SQL fields, can be returned as a set of parameters suitable for passing to a program or list primitive. This tag pair encloses any valid SQL query, and returns the results (if any) as a series of space separated fields, enclosed in quotes. This folds the entire return into a single row, so it may be used as a list of keys.
named: [sql set] SQL [/sql identifier*]
Any arbitrary SQL query can be passed with this method. No return text will be sent. This might be used for passing an order to an order database, perhaps on the order report or receipt page. An example might be:
[sql set] insert into orders values ('[value mv_order_number]', '[value name escape]', '[value address escape]', '[value city escape]', '[value state escape]', '[value zip escape]', '[value phone escape]', '[item-list] Item: [item-code] Quan: [item-quantity] Price: [item-price] [/item-list]' ) [/sql orders]
The values entered by the user are escaped, which prevents errors if quote characters have slipped into their entry.
named: [subtotal cart=cartname* noformat=1*]
old: [subtotal cart* noformat*]
mandatory: NONE
optional: cart noformat
Expands into the subtotal cost, exclusive of sales tax, of all the items
ordered so far for the optional cart
. If the noformat tag is present and non-zero, the raw number with no
currency formatting will be given.
named: [tag op=operation arg=``arg1 arg2 ... argn''] TEXT [/tag]
positional: [tag arg* arg*]text[/tag]
Performs any of a number of operations, based on the presence of arg
. The arguments that may be given are:
products
database:
[tag each products][loop-code] [loop-field name]<BR>[/tag]
n
, if specified, will select export in one of the enumerated MiniVend export
formats. The following tag will export the products database to
products.txt (or whatever you have defined its source file as), in the
format specified by the
Database directive:
[tag export products][/tag]
Same thing, except to the file products/new_products.txt:
[tag export products products/newproducts.txt][/tag]
Same thing, except the export is done with a PIPE delimiter:
[tag export products products/newproducts.txt 5][/tag]
The file is relative to the catalog directory, and only may be an absolute
path name if NoAbsolute is set to No
.
The following enables writes on the products
and sizes
databases held in MiniVend internal
DBM format:
[tag flag write]products sizes[/tag]
SQL databases are always writable if allowed by the SQL database itself -- in-memory databases will never be written.
The [tag flag build][/tag] combination forces static build of a page, even if dynamic elements are contained. Similarly, the [tag flag cache][/tag] forces search or page caching (not usually wise).
[tag log logs/transactions.txt] [item_list][item-code] [item-description] [/item_list][/tag]
The file is relative to the catalog directory, and only may be an absolute
path name if NoAbsolute is set to No
.
description_string
used as the Content-Description. For example
[tag mime My Plain Text]Your message here.[/tag]
will return
Content-Type: TEXT/PLAIN; CHARSET=US-ASCII Content-ID: [sequential, lead as in mime boundary] Content-Description: My Plain Text Your message here.
When used in concert with [tag mime boundary], [tag mime header], and [tag mime id], allows MIME attachments to be included -- typically with PGP-encrypted credit card numbers. See the demo page ord/report.html for an example.
&
#lt; and &
#91; respectively.
[tag show_tags][value whatever][/tag]
[tag time]%A, %B %d, %Y[/tag]
tag_data()
routine in
user-defined subroutines. If this is not done, the routine will error out
if the database has not previously been accessed on the page.
[tag touch products][/tag]
named: [total-cost cart*]
Expands into the total cost of all the items in the current shopping cart, including sales tax (if any).
MiniVend provides a [userdb ...]
tag to access the UserDB functions.
[userdb function=function_name username="username"* password="password"* verify="password"* oldpass="old password"* shipping="fields for shipping save" billing="fields for billing save" preferences="fields for preferences save" force_lower=1 param1=value* param2=value* ... ]
* Optional
It is normally called in an mv_click
or mv_check
setting, as in:
[set Login] mv_todo=return mv_nextpage=welcome [userdb function=login] [/set]
<FORM ACTION="[process-target]" METHOD=POST> <INPUT TYPE=hidden NAME=mv_click VALUE=Login> Username <INPUT NAME=mv_username SIZE=10> Password <INPUT NAME=mv_password SIZE=10> </FORM>
There are several global parameters that apply to any use of the userdb
functions. Most importantly, by default the database table is set to be userdb. If you must use another table name, then you should include a database=table
parameter with any call to userdb
. The global parameters (default in parens):
database Sets user database table (userdb) show Show the return value of certain functions or the error message, if any (0) force_lower Force possibly upper-case database fields to lower case session variable names (0) billing Set the billing fields (see Accounts) shipping Set the shipping fields (see Address Book) preferences Set the preferences fields (see Preferences) bill_field Set field name for accounts (accounts) addr_field Set field name for address book (address_book) pref_field Set field name for preferences (preferences) cart_field Set field name for cart storage (carts) pass_field Set field name for password (password) time_field Set field for storing last login time (time) expire_field Set field for expiration date (expire_date) acl Set field for simple access control storage (acl) file_acl Set field for file access control storage (file_acl) db_acl Set field for database access control storage (db_acl)
named: [value name=field escaped=1 set=``new value'']
positional: [value field flag*]
HTML examples:
<PARAM MV="value name"> <INPUT TYPE="text" NAME="name" VALUE="[value name]">
Expands into the current value of the customer/form input field named by field. If flag is present, single quotes will be escaped with a backslash; this allows you to contain the [value ...] tag within single quotes. (It is somewhat better to use other quoting methods.) When the value is returned, any MiniVend tags present in the value will be escaped. This prevents users from entering MiniVend tags in form values, which would be a serious security risk.
If the set
value is present, the form variable value will be set to it and the empty
string returned. Use this to ``uncheck'' a checkbox or set other form
variable values to defaults. NOTE: This is only available in new-style tags, for safety reasons.
named: [value-extended name=formfield outfile=filename* ascii=1* yes="Yes"* no="No"* joiner="char|string"* test="isfile|length|defined"* index="N|N..N|*" file_contents=1* elements=1*]
positional: [value-extended name]
HTML examples:
No match found for <PARAM MV="value-extended" MV.JOINER=" and " MV.NAME=mv_searchspec> <INPUT TYPE="text" NAME="mv_searchspec" VALUE="[value-extended name=mv_searchspec index=0]"> <INPUT TYPE="text" NAME="mv_searchspec" VALUE="[value-extended name=mv_searchspec index=1]">
Expands into the current value of the customer/form input field named by field. If there are multiple elements of that variable, it will return the value at index; by default all joined together with a space.
If the variable is a file variable coming from a multipart/form-data file upload, then the contents of that upload can be returned to the page or optionally written to the outfile.
In the special case of a file upload, the value returned is the name of the file as passed for upload.
isfile
returns true if the variable is a file upload.
length
returns the length. defined
returns whether the value has ever been set at all on a form.
*
, will return all (joined by joiner). If a range, such as 0 .. 2
, will return multiple elements.
1
for tests and the empty string for uploads.
NOTE: This is ignored if using the new syntax.
Where n is a single digit in the range 0-9. If present, it forces early interpolation of that region of MiniVend tags, and is differentiated from other early interpolation areas. The enclosed MiniVend tags will still be interpolated in the normal order, but it can usually be combined with the [post] [/post] pair to achieve the desired order.
NOTE: This is ignored if using the new syntax.
Forces early interpolation of any tag. Sometimes needed if the order of interpolation does not achieve the desired result (meaning you see MiniVend tags displayed on the page).
MiniVend 3.04 allows the definition of user tags when using the new parsed
HTML syntax (a [new] tag is on the page). They will
not work with the old syntax. 3.06 adds the tags on a server-wide basis,
defined in minivend.cfg
.
To define a tag that is catalog-specific, place UserTag directives in your catalog.cfg file. For server-wide tags, define them in minivend.cfg. Catalog-specific tags take precedence if both are defined -- in fact, you can override the base MiniVend tag set with them. The directive takes the form:
UserTag tagname property value
where tagname
is the name of the tag, property
is the attribute (described below), and value is the value of the property for that tagname.
The user tags can either be based on Perl subroutines or just be aliases for existing tags. Some quick examples are below.
An alias:
UserTag product_name Alias data products title
This will change [product_name 99-102] into [data products title 99-102],
which will output the title
database field for product code 99-102
. Don't use this with [item-data ...]
and [item-field ...]
, as they are parsed separately. You can do [product-name [item-code]]
, though.
A simple subroutine:
UserTag company_name Routine sub { "Your company name" }
When you place a [company-name] tag in a MiniVend page, the text
Your company name
will be substituted.
A subroutine with a passed text as an argument:
UserTag caps Routine sub { return "\U@_" } UserTag caps HasEndTag
The tag [caps]This text should be all upper case[/caps] will become
THIS TEXT SHOULD BE ALL UPPER CASE
.
Here is a useful one you might wish to use:
UserTag quick_table HasEndTag UserTag quick_table Interpolate UserTag quick_table Order border UserTag quick_table Routine <<EOF sub { my ($border,$input) = @_; $border = " BORDER=$border" if $border; my $out = "<TABLE ALIGN=LEFT$border>"; my @rows = split /\n+/, $input; my ($left, $right); for(@rows) { $out .= '<TR><TD ALIGN=RIGHT VALIGN=TOP>'; ($left, $right) = split /\s*:\s*/, $_, 2; $out .= '<B>' unless $left =~ /</; $out .= $left; $out .= '</B>' unless $left =~ /</; $out .= '</TD><TD VALIGN=TOP>'; $out .= $right; $out .= '</TD></TR>'; $out .= "\n"; } $out .= '</TABLE>'; } EOF
Called with:
[quick-table border=2] Name: [value name] City: [value city][if value state], [value state][/if] [value country] [/quick_table]
The properties for UserTag are are:
UserTag tagname Alias tag to insert
An Alias is the only property that does not require a Routine to process the tag.
UserTag tagname attrAlias alias attr
As an example, the standard MiniVend value tag takes a named attribute of name for the variable name, meaning that [value name=var]
will display the value of form field var
. If you put this line in catalog.cfg:
UserTag value attrAlias identifier name
then [value identifier=var]
will be an equivalent tag.
tag_loop_list
and tag_if
in lib/Vend/Interpolate.pm for an example of a nesting tag.
UserTag tagname CanNest
[tagname]
and ending [/tagname]
will be the last argument sent to the defined subroutine.
UserTag tagname HasEndTag
attribute
instead of an attribute=value
pair. It must be a recognized attribute in the tag definition, or there
will be big problems. Use this with caution!
UserTag tagname Implicit attribute value
If you want to set a standard include file to a fixed value by default, but
don't want to have to specify [include file="/long/path/to/file"]
every time, you can just put:
UserTag include Implicit file file=/long/path/to/file
and [include file]
will be the equivalent. You can still specify another value with C[include
file=``/another/path/to/file'']
UserTag tagname InsertHTML htmltag mvtag|mvtag2|mvtagN
In MiniVend's standard tags, among others, the <OPTION ...> tag has the [selected ..] and [checked ...] tags included with them, so that you can do:
<INPUT TYPE=checkbox MV="checked mvshipmode upsg" NAME=mv_shipmode> UPS Ground shipping
to expand to this:
<INPUT TYPE=checkbox CHECKED NAME=mv_shipmode> UPS Ground shipping
Providing, of course, that mv_shipmode
is equal to upsg
. If you want to turn off this behavior on a per-tag basis, add the
attribute mv.noinsert=1 to the tag on your page.
UserTag tagname InsideHTML htmltag mvtag|mvtag2|mvtagN
In MiniVend's standard tags, the only InsideHTML tag is the < SELECT> tag when used with loop, which causes this:
<SELECT MV="loop upsg upsb upsr" NAME=mv_shipmode> <OPTION VALUE="[loop-code]"> [shipping-desc [loop-code]] </SELECT>
to expand to this:
<SELECT NAME=mv_shipmode> [loop upsg upsb upsr] <OPTION VALUE="[loop-code]"> [shipping-desc [loop-code]] [/loop] </SELECT>
Without the InsideHTML setting, the [loop ...] would have been outside of the select -- not what you want. If you want to turn off this behavior on a per-tag basis, add the attribute mv.noinside=1 to the tag on your page.
UserTag
will be re-parsed for more MiniVend tags. If it is a container, Interpolate
causes the contents of the tag to be parsed before the tag routine is run.
UserTag tagname Interpolate
UserTag tagname InvalidateCache
It does not override [tag flag build][/tag], though.
UserTag tagname Order param1 param2
[usertag argument]
instead of [usertag ARG=argument]
. If not defined, Routine is used, and MiniVend will usually do the right thing.
UserTag tagname ReplaceAttr htmltag attr
An example is the standard
HTML <
A
HREF=...> tag. If you want to use the MiniVend tag
[area pagename]
inside of it, then you would normally want to replace the
HREF attribute. So the equivalent to the following is
defined within MiniVend:
UserTag area ReplaceAttr a href
Causing this
<A MV="area pagename" HREF="a_test_page.html">
to become
<A HREF="http://yourserver/cgi/simple/pagename?X8sl2lly;;44"> when intepreted. =item ReplaceHTML
For HTML-style tag use only. Causes the tag containing the MiniVend tag to be stripped and the result of the tag to be inserted, for certain tags. For example:
UserTag company_name Routine sub { my $l = shift; return "$l: XYZ Company" } UserTag company_name HasEndTag UserTag company_name ReplaceHTML b company_name
<BR> is the HTML tag, and ``company_name'' is the MiniVend tag. At that point, the usage:
<B MV="company-name"> Company </B> --->> Company: XYZ Company
Tags not in the list will not be stripped:
<I MV="company-name"> Company </I> --->> <I>Company: XYZ Company</I>
minivend.cfg
parameter AllowGlobal is set for the catalog.
UserTag tagname Routine sub { "your perl code here!" }
The routine may use a ``here'' document for readability:
UserTag tagname Routine <<EOF sub { my ($param1, $param2, $text) = @_; return "Parameter 1 is $param1, Parameter 2 is $param2"; } EOF
The usual here documents caveats apply.
Parameters defined with the Order property will be sent to the routine first, followed by any encapsulated text (HasEndTag is set).
Note that the UserTag facility, combined with AllowGlobal, allows the user to define tags just as powerful as the standard MiniVend tags. This is not recommended for the novice, though -- keep it simple. 8-)