Documentation for the Textpattern plugin smd_multi_choice by Stef Dawson follows this short message from our sponsor ;-)
If you like my code and it soothes an otherwise unscratchable itch, feel free to show your appreciation with something from my UK Amazon wish list (or US) or donate to the Stef Dawson community coding pot, either via paypal.me/stefdawson or by following the Donate button below to PayPal. Thanks!
smd_multi_choice
A generic ‘if condition’ tester that can take action if some article, file, link, URL, <txp:variable />
or global PHP variable matches one or more tests. The difference between this and smd_if is that you do not need to nest successive tests because it performs comparisons using a switch... case
construct.
Features
- Supports all major article, file, and link variables such as section, category, custom fields, id, query string, author, body, excerpt, yahde yahde, plus checking url vars, server vars, txp and PHP vars
- Tests include equality, less than, greater than, divisible by, begins, ends, contains, and ‘character’ tests such is isalpha, isnum, etc
- Tests can either terminate when a match is found, or “fall through” to the next test (“AND” logic)
- Multiple tests can have the same outcome (“OR” logic)
- The tested field & matched value are available to the case container so you can display them
- Default condition in the event no test cases match
Author
Installation / Uninstallation
Download the plugin from either textpattern.org, or the software page, paste the code into the TXP Admin -> Plugins pane, install and enable the plugin. Visit the forum thread for more info or to report on the success or otherwise of the plugin.
To uninstall, simply delete from the Admin -> Plugins page.
Usage
The plugin gives two tags which must be used in tandem. Use <txp:smd_switch />
to tell the plugin which item
you are interested in comparing against and then use one or more <txp:smd_case />
tags inside the switch to take action depending on the value.
Use the tags in any page, form or article context. Can also be used inside file, image (in the future) or link lists to take action depending on attributes of the current item.
smd_switch
At the place you wish to compare a field with a set of values, put this container tag.
Attributes
- item : the thing you are interested in. It could be the result of another tag-in-tag, a fixed string(!), or a variable if you prefix the item with
?
. Example variables are?article_image
,?url_title
,?my_txp_var
,?my_url_var
, and so on - look_in : list of places to look for the
item
. Default:SMD_ALL
which checks all items in the following list, in order. You should never need to change this, but you may choose from any of the following and comma-separate each one you wish to consider:- txpvar : a
<txp:variable />
- svrvar : something in
$_SERVER
- file : variable from the current file in a file_download_list
- image : variable from the current image in an image_list
- link : variable from the current link in a linklist
- gbl : variable from the global article context (a.k.a.
$pretext
) - article : variable from the current article
- urlvar : something in
$_GET
or$_POST
- phpvar : something in the global scope
- txpvar : a
- leave_empty : in most cases if a variable is not set you will want it to remain that way so your switch will do nothing. But you may decide that you want the variable name itself to become the
item
, i.e. if you useditem="?quantity"
and there was no ‘quantity’ variable anywhere, it would compare against the actual word ‘quantity’. This may be useful when specifying defaults - var_prefix : if you are nesting smd_switch tags you’ll find that any inner
{smd_mc_value}
replacements will take on the values of the outer tag. For this reason you can specify a prefix that will be used in all replacements. Thus if you setvar_prefix="in_"
on your inner smd_switch tag, you would use{in_mc_value}
and{in_mc_item}
in the inner container/form. Default:smd_
- debug : set to 1 to turn on diagnostic info for all contained smd_case tags
smd_case
Inside your <txp:smd_switch>
container put one or more <txp:smd_case />
tags to test the item
against each successive value. Case tags are usually containers that will execute the enclosed content if the value
matches the item
, but see example 4 for use as a self-closing tag.
Attributes
- value : the value you want to check against. It can either be a fixed value or another field in the current context (see the
<txp:smd_switch />
tag’sitem
attribute for info). Default: unset - type : the type of test you want to perform:
- eq : Equality (the default)
- gt :
item
is greater thanvalue
- ge :
item
is greater than or equal tovalue
- lt :
item
is less thanvalue
- le :
item
is less than or equal tovalue
- divisible :
item
is wholly divisible byvalue
1 - begins :
item
starts withvalue
- contains :
item
hasvalue
somewhere within its contents - ends :
item
ends withvalue
- isnum :
value
is made up entirely of digits - isalpha :
value
is made up entirely of alphabetic characters - isalnum :
value
is made up entirely of alphanumeric characters - islower :
value
is made up entirely of lower case characters2 - isupper :
value
is made up entirely of upper case characters2 - ispunct :
value
is made up entirely of punctuation characters - isspace :
value
is made up entirely of ‘whitespace’ characters - empty :
item
is empty (i.e. has no content) — similar tovalue=""
- look_in : exactly the same options as for smd_switch except they apply to the
value
attribute - leave_empty : exactly the same behaviour for smd_switch except it applies to the
value
attribute - case_sensitive : whether you wish to take case into account when compare
item
andvalue
; 1=yes, 0=no. Default: 0 - numeric : whether you wish to compare the values numerically (1) instead of alpha-numerically (0). Useful when comparing numbers because ‘f’ is actually greater than ‘1’ in the ASCII table. Default: 0. Note that a numeric test is implied if using
type="divisible"
- fallthru : under normal circumstances, when one of the tests matches any further tests are ignored. Thus the order of the tests is important. Sometimes you may wish to take more than one action, e.g. if the item is greater than value1 then display something, and also display something else if it begins with value2. This type of “AND” condition is achieved by setting
fallthru="1"
. In the event the case matches this condition, the next case tag will still be checked. For “OR” conditions, see example 4 - default : inside any switch, one and only one of your case tags can be designated a ‘default’ by setting this attribute to 1. This default branch will be taken if none of the preceding case tags match anything. It is usually the last tag in a switch. Default: 0
- debug : set to 1 to show diagnositc information for this case tag only. Default: 0
1 This test forces ‘numeric’ on automtically. Also, 0 is regarded as not wholly divisible by any value
2 case_sensitive is automatically set to 1 for these tests
Replacement variables
Some replacement variables are available within the <txp:smd_case>
container so you may output the matched values directly, for example, in error messages:
{smd_mc_item}
(or{smd_switch}
): the value of the switchitem
being looked at{smd_mc_value}
(or{smd_case}
): the value of the casevalue
that matched theitem
When testing more than one value to produce a single outcome, the most recent value that matches is the one assigned to the replacement variable. Note that the smd_
part is the default setting and may be changed with the var_prefix
attribute.
Examples
Example 1
On your error_default page you could put this:
<txp:smd_switch item="?txp_error_code">
<txp:smd_case value="403">
<p>Forbidden access. Code: 403</p>
</txp:smd_case>
<txp:smd_case value="404">
<p>Page not found. Code: 404</p>
</txp:smd_case>
<txp:smd_case value="500">
<p>Something went horribly wrong. Code: 500</p>
</txp:smd_case>
<txp:smd_case default="1">
<p>Whoops! Error code: {smd_mc_item} occurred</p>
</txp:smd_case>
</txp:smd_switch>
Example 2
Test some value obtained from public-side form input:
<txp:smd_switch item="?quantity" look_in="urlvar">
<txp:smd_case value="2" type="lt"
numeric="1">
<p>Value {smd_switch} is too small</p>
</txp:smd_case>
<txp:smd_case value="20" type="gt"
numeric="1">
<p>Value {smd_switch} is too large</p>
</txp:smd_case>
</txp:smd_switch>
Example 3
Building on example 2, this runs the 2nd and 3rd tests regardless of whether the 2nd one returned true. It also adds a check to see if the quantity
URL variable is set at all and issues a warning of not (an empty <txp:smd_case>
is the same as <txp:smd_case value="">
)
<txp:smd_switch item="?quantity" look_in="urlvar">
<txp:smd_case>
Please supply a quantity<br />
</txp:smd_case>
<txp:smd_case value="2" type="lt"
numeric="1">
Value {smd_switch} is too small<br />
</txp:smd_case>
<txp:smd_case value="20" type="gt"
numeric="1" fallthru="1">
Value {smd_switch} is too large<br />
</txp:smd_case>
<txp:smd_case value="100" type="gt"
numeric="1">
... and out of this world!<br />
</txp:smd_case>
<txp:smd_case default="1">
Everything's fine
</txp:smd_case>
</txp:smd_switch>
Thus, you see the following if you add these values to the address bar:
?quantity=1
: Value 1 is too small?quantity=15
: Everything’s fine?quantity=25
: Value 25 is too large?quantity=125
: Value 125 is too large… and out of this world!
Example 4
Sometimes you may want to perform the same action for a number of matches. For these instances you may use the <txp:smd_case />
tag in its Single form. List all the cases that you want to have the same outcome, then use the container of the last one to perform the action if any of the preceding cases matched.
<txp:smd_switch item="?custom1">
<txp:smd_case value="3" type="divisible" />
<txp:smd_case value="7" type="divisible" />
<txp:smd_case value="9" type="divisible">
{smd_switch} is divisible by 3, 7 or 9
</txp:smd_case>
<txp:smd_case value="5" type="ends" />
<txp:smd_case value="0" type="ends">
Yay! Numbers ending in 5 or 0 win a teddy.
</txp:smd_case>
</txp:smd_switch>
If you add fallthru="1"
to the value="9"
case tag, both ‘divisible’ and ‘teddy bear’ sets of conditions would be tested and you’d see varying combinations of the output based on the contents of custom1.
Example 5
This one checks that the URL variable qty
is within the range of a stock
custom field. This one uses a nested smd_switch
tag. The first (outer) switch checks if the value is numeric and then uses a second switch to compare its value to the stock level in the custom field. If the outer switch detects the value is not numeric, the default case fires to inform the visitor of the error.
<txp:smd_switch item="?qty">
<txp:smd_case type="isnum">
<txp:smd_switch item="?qty" var_prefix="inner_">
<txp:smd_case value="0">
Please select a quantity to order
</txp:smd_case>
<txp:smd_case value="?stock" type="le">
There are enough of those in stock. Place order?
</txp:smd_case>
<txp:smd_case default="1" value="?stock">
There are only {inner_mc_value} in stock. Please choose a lower number
</txp:smd_case>
</txp:smd_switch>
</txp:smd_case>
<txp:smd_case default="1" value="?stock">
Sorry, "{smd_mc_item}" is not valid input. Please choose a valid order quantity.
</txp:smd_case>
</txp:smd_switch>
So if someone enters ?qty=0
or ?qty=fred
then a special message is shown to prompt them to enter a valid number. If the qty
variable is lower than the stock level of the current article then all is well. But if any other value is used, the default
condition of the inner smd_switch
kicks in and tells the visitor that there are not enough to satisfy their ravenous needs.
A couple of other things to note:
- the inner switch uses the
var_prefix
attribute so the variable can be displayed correctly to the visitor without clashing with the value in the outer switch. In this case the switch values happen to be the same so it doesn’t really matter, but if you were testing a separate variable then it might - the default cases both use
value="?stock"
even though they would appear not to be strictly necessary. They are used so the replacement variables{smd_mc_item}
and{inner_mc_value}
can be inserted in the output. If you omit thevalue
attribute then the replacements are not ‘primed’ because the case tag does not know where to look for its value
Changelog
- 10 Apr 09 | 0.10 | Initial release
- 01 Aug 10 | 0.20 | Added empty type (thanks gomedia) ; added
var_prefix
; fixed default case firing unnecessarily ; fixed problem with multiple switch tags on a page
Source code
If you’d rather spend time with the bytes, you’ll need to step into the view source page.
Legacy software
If, for some inexplicable reason, you need the un-current version of a plugin, it can probably be found on the plugin archive page.
Experimental software
If you’re feeling brave, or fancy dipping your toe in shark-infested water, you can test out some of my beta code. It can be found on the plugin beta page.