Documentation for the Textpattern plugin smd_qr_code by Stef Dawson follows this short message from our sponsor ;-)
If you like my code and find it useful, 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_qr_code
Create Quick Response 2-D barcodes on the fly containing a variety of data: text, URL links, contact details, geographical location data, wifi hotspot requests, or your own custom formats. Choose to embed the barcode directly on your page or offer it as a download.
Author / credits
Written by Stef Dawson. Credits also go to the awesome Google Charts API. Many thanks to all involved.
Installation / uninstallation
Requires TXP 4.4.0+, PHP 5 (with CURL) and Internet access
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. To uninstall, delete from the Admin -> Plugins page.
Visit the forum thread for more info or to report on the success or otherwise of the plugin.
Usage: <txp:smd_qr_code />
The plugin adds one tag, which you can use to embed a QR code on your page. It has a variety of attributes.
Data attributes
- type : the type of QR code to generate. Define your own, or use one of the built-in formats:
- text : the default
- link : a hyperlink. The
http[s]://
prefix is optional and will be added if omitted - bookmark
- sms : send a text message
- phone
- contact : a MECARD
- vcard : a compact version of the full vcard spec
- geo : geographical location (decimal latitude, longitude and height above the earth’s surface)
- wifi : wifi hotspot login credentials (WEP or WPA protocols supported)
- data : the information to put in the QR code. The data is dependent on the
type
— see the data table for details on the quantity and order of information you put in this attribute for the built-in types. Delimit each piece of data with a pipe character (though this can be changed with thedelim
attribute, if required). For example,type="bookmark" data="20,000 Leagues under the Sea|www.jules-verne.co.uk/"
. The limit of the data attribute is about 2KB - delim : the delimiter to use between
data
items. Default:|
(pipe) - escape : Escape HTML entities such as
<
,>
and&
. Useescape="html"
to switch this on. Default: unset
Output / display attributes
- format : whether you wish to
view
the barcode inline (inside an<img>
tag), force it todownload
, or output theraw
link so you can craft your own use for it. Default:view
- width : width of the code, in pixels. Defaut: 200
- height : height of the code, in pixels. Default: 200
- quality : the amount of error correction that the barcode can tolerate:
- L — Low: 7% (default)
- M — Medium: 15%
- Q — Quartile: 25%
- H — High: 30%
- margin : the margin (in QR code “rows”) around the image. Default: 4. Note that, depending on the quality and size settings, some adjacent values don’t appear to ‘do’ anything. For example, a 200×200 ‘L’ quality image looks the same whether you pick a margin of 0, 1 or 2. The margin steps up a size for 3, 4 and 5, then up again for 6-10, and so on. This is an idiosyncracy of Google’s Charts API (or the QR code spec?), not a fault with the plugin
- bgcol : background colour as an RGB hex code (without the #). Default: unset
- alpha : alpha transparency as a hex value from 00 (transparent) to FF (solid). Default: unset
- wraptag : the (X)HTML tag — specified without angle brackets — to wrap around the output. Default: unset
- class : the CSS classname to apply to the wraptag (if present) or the
<img>
tag if you have chosenformat="view"
. Default: unset - html_id : the HTML id to apply to the wraptag (if present) or the
<img>
tag if you have chosenformat="view"
. Default: unset - title : Set the
<img>
tag’s title attribute (often used as a tooltip). Only of use whenformat="view"
. Default: unset
Validation attributes
- validate : whether to validate all fields (1, the default), no fields (0) or the given list of data fields. The list is delimited by
validelim
(default: comma). Consult the data table for details on the names of the fields you can use. After each field you may also add adelim
character and then a regular expression to validate this field against, which will override the built-in regex. See example 5.If you specify one or two fields to validate — perhaps you just want to adjust a single regex to taste — you’ll find that the remaining fields are “switched off” and not validated. To save you having to list them all, you can use a shortcut: just specify1
as one of your list items and the remaining fields will be included in the validation with their original regexes.You may also copy regexes if you don’t wish to define them again. Specify the field as usual and then the special code SMD_REGEX_name_of_field_to_copy. - validelim : the delimiter to use between your list of items to
validate
. Default:,
(comma)
Customisation attributes
- layout : define your own custom layout system. Use
{name-of-variable}
in your definition to have the data value injected at runtime. See custom types - transform : define your own custom transformation to apply to particular data items. Specify
type.field|name-of-function|optional|args|...
. See custom transforms - prefix : prefix for new parameters that are created by your transformations. Default:
SMD_QR_
The plugin checks that you supply all information for your chosen type and, if validate
is set validates each field with a regular expression. Any deviation will result in an error being triggered.
Note that if you wish to designate an item as ‘empty’ (i.e. you don’t want to supply that parameter) you can put in the special code {smd_empty}
. It is not enough to simply leave it blank because the plugin expects all fields to be filled in with something. The QR code will still contain the field, it will just have no data assigned to it. If you don’t like the built-in formats, create your own.
The code should be cached by your browser for 24 hours.
Data table for default types
Here are all the type
s available and the fields they require in the data
attribute, from left to right. The names used here are the names you refer to the fields when listing them in your validate
attribute.
type | data attributes | ||||
---|---|---|---|---|---|
text | text | ||||
link | url | ||||
bookmark | title | url | |||
sms | phone | text | |||
phone | phone | ||||
subject | message | ||||
contact | name | address | phone | ||
vcard | name | url | address | phone | |
geo | lat | lon | height | ||
wifi | wifi_protocol | ssid | pass |
Custom types
You may create your own custom data formats for your QR codes. As well as being able to designate a custom regular expression to validate the data value, you can also specify callbacks to transform the data value prior to its validation. This allows you to do things like tidy up links, add suffixes, sanitize data, etc.
Let’s say you don’t like the built-in vcard implementation and wanted to drop the ADR property, while adding the CELL property. You can define your own by using the following attributes (line breaks added only for clarity: they should not be in your definition) :
type="my_vcard" layout="BEGIN:VCARD\r\n
N:{SMD_QR_formatted_name}\r\n
FN:{name}\r\n
EMAIL:{email}\r\n
URL:{url}\r\n
TEL:{phone}\r\n
CELL:{cell}\r\n
END:VCARD"
A few things to note:
- You can name the
type
anything you like (even the same name as one of the existing types: your version will be used instead) - The vcard spec (certainly v3+) states that the
N:
property is mandatory. It’s merely a reformatted version of theFN:
so, to save you having to add it manually, the plugin applies a custom transform calledsplitrevjoin
(more info in the custom transforms section). Because it’s a computed field, the plugin designates it with anSMD_QR_
prefix. If you wanted to flaunt the spec and omit this value, just remove that entry from yourlayout
- The
{cell}
replacement variable isn’t one of the built-in supported formats (i.e. one of the parameters listed in the data table). To help you out, the plugin assigns a default regular expression “one or more characters” to any new parameters, but if you wish to tighten this you can specify your own regex via thevalidate
attribute - Any URLs are reformatted to begin with
http://
if you omit the prefix. This is another built-in transform which you can override or suppress if you prefer
With this custom format in place you can specify a data
attribute like this (again, newlines are for clarity only) :
data="Stef Dawson
| some@mail.com
| stefdawson.com
| +44 (0)1234 567 890
| +44 (0)7777 098 765"
Your QR code would be generated with the above data in it. If you wanted to use the same format across a number of codes, you could define your format in a <txp:variable />
and use TXP’s standard tag-in-attribute syntax to reuse it.
Since the new field ‘cell’ will be validated using the most permissive regex and we already have a perfectly good expression defined for ‘phone’ it’d be a shame to have to repeat ourselves. So you can do this:
validate="1, cell:SMD_REGEX_PHONE"
to copy the ‘phone’ regex over to the ‘cell’ field. The ‘1’ just makes sure that all the remaining fields are validated as normal. Without that, only the cell and any other fields you explicitly defined in the list would be validated. If you would like to see a list of the built-in regexes, use debug="1"
(or 2 for more verbose output).
Custom transforms
Before validation, each piece of data may be put through a mangle to reformat it. You could use this to sanitize data, prefix it, suffix it, fetch other data, or create new entries by twisting a given data parameter. The following default transforms are built-in:
- linkify : prefix any URL that does not begin with
http://
- splitrevjoin : takes someone’s name, splits it at space, reverses the order of the data, and then recombines it with a semicolon between each field. Thus
Stef Dawson
becomesDawson;Stef
Transformations can be applied to any data parameter. You choose which by using the following syntax:
transform="type.field|function_name|optional|attributes|..."
So to capitalize the vcard’s ‘name’ you could use PHP’s built-in function strtoupper()
like this:
transform="vcard.name|strtoupper"
You can use a shorthand ‘wildcard’ notation if you wish to apply the same transform to the same parameter in different types (though admittedly, this has limited use). The plugin uses this with its default URL transformation by using: *.url|linkify
.
If you try the above though you will receive a plugin warning Invalid or unregistered transform function
. That’s a security message because only registered functions are permitted to run transformations. To register a function, use Textpattern’s register_callback()
function in some PHP:
register_callback('strtoupper', 'smd_qr_code', 'add_transform');
You can of course use your own functions if you wish. The signature of your function should be:
- (string) Data value to transform
- (array) Optional values that your transform needs
The additional parameters are passed, in order, from the transform
attribute. Note that you can only use functions (either your own, or PHP/TXP functions) if they either take a single string or a string plus an array as arguments. Trying to use any more complicated functions or attributes of the wrong type will likely result in warnings or errors being thrown.
If your custom function returns a single string value, that will become the parameter’s new value. If, however, you return an array of idx => values then any idx that matches the name of the parameter will replace the original. Any additional idx values become new parameters, prefixed with SMD_QR_
. Let’s look at the built-in splitrevjoin()
function:
public function splitrevjoin($item, $args=array()) {
// $args: 0 = variable name, 1 = split char, 2 = join char
if (count($args) == 3) {
$outval = join(
$args[2]
, array_reverse(
explode( $args[1], $item )
)
);
return array($args[0] => $outval);
} else {
return $item;
}
}
In this function, we have assumed that the transform’s parameters are:
$item
: the data value$args[0]
: the name of the new parameter$args[1]
: the split character$args[2]
: the rejoin character
All these values are passed in like this: vcard.name|splitrevjoin|formatted_name| |;
which means we’re telling the transform to process the $item
and return a new parameter called formatted_name
after splitting the $item
at space and reconstituting the parts as a string, delimited by a semicolon.
If we’d returned name
instead of formatted_name
, the existing parameter would have been overwritten. Since the goal of this function is to reformat the person’s name into a form suitable for the vcard’s N:
attribute, we’re leaving the original intact and making a new value.
Finally, to distinguish the input values from computed values such as this one, the plugin will automatically prefix all new parameters with SMD_QR_
. Thus to use it in your layout, remember you need to specify {SMD_QR_formatted_name}
. The prefix can be changed via the plugin’s prefix
attribute.
Examples
Example 1: Bookmark permlinks
In your default Form put a QR code alongside your article heading so people can bookmark the article by taking a picture with their smart phone:
<h1 class="entry-title">
<txp:permlink><txp:title /></txp:permlink>
<txp:smd_qr_code type="bookmark"
data='<txp:title />|<txp:permlink />'
width="50" height="50"
quality="Q" />
</h1>
Notice that since the image size has been reduced to fit alongside the title, the quality (error detection/correction) has been increased to compensate.
Example 2: Author contact details
If you have smd_bio installed you could add the following code to the ‘published by’ segment of your articles. It will display a QR code for the contact details of the article’s author, thus visitors can scan the barcode and have the author’s MECARD added directly to their address books:
<p class="published">
<txp:posted /> by <txp:author title="0" />
<txp:smd_qr_code type="contact"
data='<txp:author />
| <txp:smd_bio_info items="address" label="" />
| <txp:smd_bio_info items="phone" label="" />
| <txp:smd_bio_info items="email" label="" /> />'
bgcol="bea7d0" margin="1" />
</p>
This one has a natty, thin purple border too courtesy of the bgcol
and margin
attributes.
Alternatively, in VCARD format:
<txp:variable
name="address"><txp:smd_bio_info
items="address" label="" /></txp:variable>
<p class="published">
<txp:posted /> by <txp:author title="0" />
<txp:smd_qr_code type="vcard"
data='<txp:author />
| <txp:smd_bio_info items="email" label="" /> />'
| <txp:smd_bio_info items="website" label="" />
| <txp:if_variable
name="address"
value="">{smd_empty}<txp:else /><txp:variable
name="address" /></txp:if_variable>
| <txp:smd_bio_info items="phone" label="" />
bgcol="bea7d0" margin="1" />
</p>
Note in this case we have checked if the address is empty and supplied the {smd_empty}
parameter as a convenience. You would probably enforce this upstream at data collection point, but this serves to demonstrate that you can defensively prevent smd_qr_code validation errors by employing similar techniques on certain optional fields.
Example 3: Geographic location
Organising a flashmob on Mount Kilimanjaro? Make sure people can find you by publishing a QR code on your site:
<txp:smd_qr_code type="geo"
data="-3.07583 | 37.35333 | 5895" />
Example 4: Raw links
<a href="<txp:smd_qr_code
type="link" data="myfabsite.com/vouchers"
format="raw" />">Download your voucher</a>
While this one is just a boring URL link there’s nothing to stop you generating a personal voucher code, perhaps after they have submitted their contact details via zem_contact_reborn, and tacking it onto the end of the URL.
Example 5: Overriding regexes
<txp:smd_qr_code
type="bookmark" delim="#"
validate="title, url#%^(file://|http://|ftp://).+$%"
data="Bookmark me # ftp://stefdawson.com" />
A few things to note about this one:
- The delimiter has been changed because the regular expression uses pipe symbols in its definition
- The title is still being validated, and will use the built-in regular expression
- The ‘url’ regex is going to be validated using the given regex including start/end delimiters. Normally we’d use a
/
but in this case we have chosen%
as the start/end character because we’re using/
s in the regex itself, which means we don’t have to escape them
Changelog
31 Mar 11 | 0.10 | Initial public release
02 Apr 11 | 0.20 | Added title
attribute for the <img>
tag ; added vcard type (thanks gomedia) ; added validate
and validelim
to allow regex overrides ; fixed url regex ; improved error reporting ; permitted debug
to aid in tracking down regex / validation errors
04 Apr 11 | 0.30 | Wrote more flexible, custom interface to Google Charts API ; added layout
, transform
and prefix
attributes ; improved validate
attribute
05 Apr 11 | 0.31 | Double-quotes not single quotes for proper backslashing ; fixed callback warning when no plugin callbacks defined (both thanks gomedia)
Source code
If you’d rather frolic in the raw code halls, 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 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.