Documentation for the Textpattern plugin smd_each by Stef Dawson follows this short message from our sponsor ;-)
If you like my code and it makes your site better, 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_each
Features
- Iterate over any variables you can get your hands on. These can be anything from the current article (custom field, article_image, etc), any URL/SERVER variable or cookie (subject to normal escaping rules) or any
<txp:variable />
- Include or exclude particular variables, or only choose variables that match particular text
- Iterate over subsets of data contained in any field
- Choose to process each variable one by one with a form, or collect them together into a delimited list to be processed only once by the form
- Provides free headaches if you don’t keep your wits about you
Author
Stef Dawson. For other software by me, or to make a donation, see the software page.
Installation / Uninstallation
Download the plugin from either textpattern.org, or the software page above, paste the code into the TXP Admin -> Plugins pane, install and enable the plugin. Visit the forum thread for more info or to report a bug/feature request.
To remove the plugin, simply delete it from the Admin->Plugins tab.
Usage
For some ideas on usage scenarios, see the examples.
smd_each
Place one or more smd_each tags in any article, page or form, supply any of the following options to configure it and use a form (or container) to define what to do with each matching variable.
In a nutshell, it grabs every array from the places you specify, allows you to filter the array with matches or specific items, then assigns each successive name/value pair to two replacement tags that you can use in your form to do stuff. You could simply display the values or populate new tables with them, plug values into queries, create smd_vars, test the values with smd_if, you name it.
Attributes
- type : where to look for variables. They can be combined into a comma-separated list if you wish to search more than one place at once. Options are:
field
: a TXP article field (the default)urlvar
: the URL, e.g. name1=val&name2=val&…svrvar
: the server environment variablescookie
: any user cookiestxpvar
: a value from any<txp:variable />
tagfixed
: specify your own list of variables to inject into the mix (viainclude
)
- include : base list of variable names you definitely want to be returned in the result. If you are using
fixed
as one of thetype
s you can add your own variables here, delimited byparamdelim
. For exampleinclude="keywords, my_var:north:south:east:west"
would include thekeywords
article field and createmy_var
, giving it a value of “north, south, east, west”. Note that if you are using a custom field, it is likely to have been converted to all lower case by Textpattern, so you should use an all lower case name here - exclude : base list of variable names you definitely do not want to be returned in the result
- match : list of text strings to search for to refine the returned variables. By default this will match against every variable in every location you specified in
type
. It is automatically wild so will match portions of a variable - matchwith : defaults to
name
which looks only at the variable’s name for a match. Can be set tovalue
to look at its value orname, value
to look in both for matches - subset : if you think your variables are going to contain lists themselves, specify
subset="1"
to have the plugin add each pseudo-variable to the array. For example, if you article_image field contained14, 6, 17, 3, 9
you would get five more variables calledarticle_image_1
(value:14),article_image_2
(value: 6), and so on.Note that you will also get the full article_image (and all other matching non-subset vars) included. If you wish to only see variables that contain sublists of data, usesubset="2"
- var_prefix : if you are nesting smd_each tags you’ll find that any inner
{smd_var_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="opt_"
on your inner smd_each tag, you would use{opt_var_value}
and {opt_var_name} in the inner container/form. Default:smd_
- form : the TXP form to execute for every matching variable. If not specified, the container will be used. If there’s no container, a default form with just the {smd_var_value} is used
- collate : prevent the
form
being executed for every variable. Instead, collect the variable names internally and then process the entire list by the form once only, after all variables have been read. See collate mode - delim : the delimiter to use for specifying plugin options. Defaults to comma (,)
- paramdelim : the delimiter to use for specifying inter-value plugin options (for example in collate mode). Defaults to colon (:)
- outdelim : the delimiter to use to separate each variable displayed in collate mode
- wraptag : the (X)HTML tag to wrap the form in, e.g.
wraptag="ul"
- break : the (X)HTML tag to wrap each call to the form in, e.g.
break="li"
- class : the CSS class name to give to the wraptag
Replacement tags
For every matching variable, you can use the following replacement tags in your form:
- {smd_var_name} : the variable name
- {smd_var_value} : the variable’s value
- {smd_var_counter} : the variable’s position in the list (1, 2, 3…)
- {smd_var_total} : the total number of matching variables being iterated
(Note that each replacement tag will have whatever var_prefix
you have designated: the default is smd_
).
These can be used for whatever devious means you see fit. e.g.
<txp:article_custom id="{smd_var_value}" />
will display the given article for each matching ID.<txp:article keywords="{smd_var_value}" />
in collate mode, might display the given articles that have keywords matching every user-submitted search term<txp:smd_if field="{smd_var_counter}" operator="eq" value="{smd_var_total}">This is the last item</txp:smd_if>
Collate mode
Instead of parsing each variable with the form/container, you may elect to internally ‘collect’ all matching variables and output them in one big list via the form. Thus, the form is only called once at the end. It may seem useless but it can be of value for creating lists of things from each matching variable.
Starting simply, collate="1"
switches collation mode on. If the plugin matched 3 variables from your article and you were to use the replacement tags in your form like this:
The matching vars: {smd_var_name} = {smd_var_value}
you might get this:
The matching vars: section,category1,category2 = article,news,politics
Compare that with the regular mode, which outputs:
The matching vars: section = article
The matching vars: category1 = news
The matching vars: category2 = politics
Sometimes it’s useful to be able to put quotes around each item; you can tell collate mode to do that:
collate="quote:{smd_var_value}"
You would then get:
The matching vars: section,category1,category2 = 'article','news','politics'
The delimiter (a comma in this case) can be overridden with the outdelim
attribute. You can quote more than one thing at once by specifying the items as a delimited list:
collate="quote:{smd_var_name}:{smd_var_value}"
but there’s not much point because there are only two replacement tags and you can thus use the shortcut collate="quote"
to quote them all. The delimiter used between items (the colon) can be overriden with the paramdelim
attribute.
The second special feature of collation mode is that you do not have to always output the entire list. You can grab individual entities from within the internal array by using the ‘#’ notation in your form:
{smd_var_value} might output 'article','news','politics' (as before)
{smd_var_value#1} would only output article
{smd_var_name#3} would only output category2
Note that when pulling out individual entries they do not get quotes added to them, regardless of whether you used quote
or not. This is because it is a single item so you can easily put the quotes in the form itself (viz: "{smd_var_name#2}"
)
Examples
Example 1
Display each article image from a comma-separated list of IDs in the Article Image field.
<txp:smd_each include="article_image" subset="2">
<txp:image id="{smd_var_value}" />
</txp:smd_each>
Example 2
Display each article image from a comma-separated list of IDs in the Article Image field, and also allow IDs to be given in the URL line via the variable name my_image_list
:
<txp:smd_each type="field, urlvar"
include="article_image, my_image_list"
subset="2" form="varout" var_prefix="me_" />
And in form varout
:
<txp:image id="{me_var_value}" />
Example 3
This is simply to highlight the differences between the various matching modes. Let’s take a simple article:
- section: animals
- title (url_title) : The lion (the-lion)
- category1: mammal
- category2: dangerous
- article_image: 25, 28, 12
- keywords: big, cat, mane, fur, teeth, roar, chomp, ouch
- custom1 (“origin”): africa
There are a whole host of other variables (switch debug=“1” on to see them all for your chosen type
s) but we’ll concentrate on these for now to keep things simple.
tag options | vars returned | remarks |
---|---|---|
match=“cat” | category1, category2 | default is to match name only |
match=“cat” matchwith=“name, value” | category1, category2, keywords, id_keywords | now checks value as well |
match=“cat” include=“article_image” | category1, category2, article_image | includes are always selected |
match=“cat” include=“article_image, origin” subset=“1” | category1, category2, origin, article_image, article_image_1, article_image_2, article_image_3 | looked “inside” each var to find any lists |
match=“cat” include=“article_image, origin” subset=“2” | article_image_1, article_image_2, article_image_3 | return only data sets that contain lists and removes the aggregate (base) entry |
match=“cat, article_image” matchwith=“name,value” subset=“2” | article_image_1, article_image_2, article_image_3, keywords, id_keywords | checks both name and value for each match term, and only shows items that have lists in them (if keywords held just one item “cat” it would not be displayed) |
Note that if you are using this tag in an article, the ‘body’ may match because it contains the smd_each tag which contains the very information you are matching! In this case, adding exclude="body"
will remove it from the results.
Example 4
From a page template, allow visitors to display any number of articles.
<form name="show_arts" action="/my/results/page">
<txp:article_custom form="list_checks"
category="animals" limit="999" />
<input type="submit" />
</form>
Your form list_checks
simply displays the article title and a checkbox:
<li>
<txp:title /><input type="checkbox"
name="article_lists[]"
value="<txp:article_id />" />
</li>
When the user submits the form we can use smd_each to find which checkboxes have been clicked and show the relevant articles:
<txp:smd_each type="urlvar"
match="article_lists" subset="2">
<txp:article_custom id="{smd_var_value}" />
</txp:smd_each>
Alternatively, if you are using a copy of TXP that supports lists in article_custom’s id
attribute you can drop the subset
.
Changelog
- 12 Jun 08 | 0.1 | Initial release
- 22 Jun 08 | 0.11 | Added type=fixed (thanks mrdale)
- 04 Apr 09 | 0.12 | Fixed
subset="2"
bug with single entries (thanks jeremywood) ; added{var_counter}
and{var_total}
(thanks mrdale) - 30 Aug 09 | 0.2 | Added
var_prefix
attribute and set it tosmd_
by default
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 a legacy version of a plugin, it can probably be found on the plugin archive page.
Experimental software
If you’re feeling brave, or fancy chucking your keys in the bowl, you can test out some of my beta code. It can be found on the plugin beta page.