Much of the information Textpattern tags need to build page templates and other functionality is transferred by the means of attributes. For instance, the tag
<txp:section /> uses its
title attribute’s value to output either a section’s title or name:
<txp:section title="1" /> [...]
Textpattern tags can be used without further thoughts as an attribute value for HTML elements. A frequent use case is the assignment of individual classes to a page’s
body element. I have acquainted the habit of deriving this class name from the active section as returned by
<body class="<txp:section title="0" />"> [...]
XML purists may sigh at the sight of such nestings, and it requires a certain amount of practice to keep all those quotes and angle brackets in an appropriate balance. Anyhow, it works due to the simple search’n‘replace algorithm Textpattern employs to transform tags into their “real” values.
A Gordian Textpattern Knot
Things turn really bad and Textpattern fails to decode tag patterns at occasions where one Textpattern tag would be required as an attribute for another enclosing tag.
Usage example: Reading an e-mail address from an article’s custom field #1, a useful facility for a website collecting contributions from many authors, enabling them to leave their e-mail address with the articles they write by jotting it into a custom field. A naive approach would require this tag arrangement:
<txp:email email="<txp:custom_field name="custom1" />" />
Alas, Textpattern stops its examination of those tags on the first occurrence of “/>” and therefore fails miserably.
Tags in tags
Implementing such “Tags in Tags” requires a dash of PHP, the immediate invocation of tag handler functions and the application of basic knowledge regarding Textpattern’s attribute passing methods. Though this sounds complicated, one can apply a small set of reproducable steps:
Step 1: Start at the center, find your way out
Using the example from above the innermost tag is
txp:custom_field, embedded into
txp:email. Additional outer layers are detectable using the same method.
Step 2: Build a PHP snippet to invoke tag handlers according to this determined sequence
Tag handler functions are named like their counterpart tags (stripping the
txp:custom_field is therefore handled by a PHP function named
'name' => 'value' pairs.
So the innermost part equals this PHP block:
custom_field (array( 'name' => 'custom1' ));
Using the value returned by this block we can feed the outer layers. To keep things tidy we use an intermediate storage for the e-mail address (
$a). Pass other attributes by comma separated
'name' => 'value' pairs in any random order.
$a = custom_field (array( 'name' => 'custom1' )); email (array( 'email' => $a, 'linktext' => 'mail me' ));
Step 3: Package it nicely into a form
Add a new “misc” type form to keep this PHP code and apply it where needed by
txp:output_form. Bearing a little loss of tidiness the whole sequence can be included into an article form as well. Output the result of this whole shebang with
<txp:php> $a = custom_field (array ('name' => 'custom1')); echo email (array( 'email' => $a, 'linktext' => 'mail me' )); </txp:php>
One single pitfall
Textpattern tags without any attribute require an empty array for the tag handler function:
<txp:php> $a = section (array ()); </txp:php>
In case it doesn’t work out in the first place…
If the actual results are rather disappointing,
dmp() can be used to dump intermediate results. Try comparing your expected results with those written on the page. Sticking with our example, you would expect to find the contents of custom field 1 read into
<txp:php> $a = custom_field ( array ('name' => 'custom1') ); dmp ($a); echo email (array('email' => $a, 'linktext' => 'mail me')); </txp:php>
Applying this method is a way of reducing the need for a specialized plug in, covering Textpattern applications diverging and expanding the common static tag arrangements.
(Rope image by sxc.hu)