TextformatterTagParser by

Substitutes tags in a given text block with values from a context (or an array of contexts). Each context provider must be an instance of WireData. This means that almost any object from ProcessWire can be used by the parser to do substitutions.

h1. Tag Parsing Textformatter Module For ProcessWire

Substitutes tags in a given text block with values from a context (or an array of contexts). Each context provider must be an instance of WireData. This means that almost any object from ProcessWire can be used by the parser to do substitutions.

Version 2.0 adds the ability to semi-randomly generate alternate texts from options embedded within your input.

Given an input string such as:

bc. "Date: {datetime}\nUser: {name}\nIP: {REMOTE_ADDR}"

...and a user object as context, you might get something like this as the result...

bc.. Date: 12th September 2012, 14:45
User: ryan

p. ...of course, your mileage may vary.

h2. Installation

# Copy TextformatterTagParser.module to your site/modules directory
# Login to the admin interface
# Navigate to the modules page
# Click the "Check for new modules"
# Click on the name "TextformatterTagParser" in the message that appears or scroll to the bottom of the screen to locate the correct entry
# Click the "Install" button.

h2. Tags In The Input

You can embed tags in the input text block in the positions in which you'd like the parser to make a substitution from the context it has been given. These tags are always formed by matched curly braces and must take one of these forms...

# {fieldname}
# {context.fieldname}

The first form can be used regardless of how many contexts are setup in the parser, whilst the second form is used to specified which context to extract the fieldname from when using multiple contexts. For example, {page.name} is more specific than just {name}. If no context specifier is used in a tag then contexts will be searched for a match in the order in which they appear in the context array and the first match will be used for the substitution.

The value of _fieldname_ can be any field accessible in any context or from the $_SERVER globals or one of the following special fields...

|_. Special Tag |_. Description |
| {datetime} | The current date & time as formatted according to the dateFormat value in your site's config.php file. |

Special tags override other context fields with the same name so if you want to include the datetime from one of your context objects you need to specify the context in the tag (eg. "{login.datetime}").

h2. Transformation Of Tag Values

It is possible to have the parser apply a number of transformations to the value used to replace a given tag. You can specify a transformation to perform on the substituted value of a tag by appending it to the end of the tag like this @{name>upper}@ or @{page.name>title}@.

You can chain transformations so: @{page.title>lower>url}@ which will lowercase the title field value and then URL encode it.

|_. Transformation |_. Description |
| lower | Runs the value through @mb_strtolower()@ or @strtolower()@ |
| upper | Runs the value through @mb_strtoupper()@ or @strtoupper()@ |
| title | Runs the value through @mb_convert_case( , MB_CASE_TITLE, )@ or @ucwords()@ |
| url | URL encodes the value unless URL encoding is set globally |
| encode | A deprecated alias for the 'url' transformation |
| base64 | Base64 encodes the value |
| strip | Runs the value through @strip_tags()@ |
| email | Limits substitution to a single, trimmed line. Several possible line-ending characters are taken into account when splitting the substituted value into a single line. |
| html | Runs the value through @htmlspecialchars( , ENT_QUOTES, 'utf-8' )@ |
| initial | Returns the initial letter of the string |
| initcap | Returns the initial letter of the string capitalised and postfixed with '.' |
| initials | Returns the initial letters of each word of the field |
| initcaps | Returns the initial letters of each word of the field capitalised and postfixed with '.' |
| thinspaces | Thins out multiple spaces, replacing them with a single space |
| nospaces | Strips spaces from the field. |
| nl2br | Converts newlines to html breaks. |
| nl2space | Converts newlines to spaces; essentially collapsing multiline text. |
| name | Passes the value through TextformatterNameSanitiserEn, if it is installed. |
| (integer) _n_ | Select the [*n*][^th^] word from the input string |

You can also specify which of the above are to be applied to *all* the substitutions in a text by setting that transform name to true on the parser (see usage example.)

h2. Usage

h3. Getting a parser object:

bc. $parser = wire()->modules->get("TextformatterTagParser");

h3. Setting a single context:

bc. $parser->set('context', $user);

If you are only setting a single context then the shorter _{fieldname}_ tag format will be sufficient for the parser.

h3. Setting multiple contexts:

bc. $parser->set('context', array('user'=>$user, 'page'=>$page) );

If you are using multiple contexts, you will probably need to use the _{context.fieldname}_ tag format in your input strings to avoid ambiguity when the parser looks for substitutions.

h3. Parsing a string:

Parsing is done using the format() method.

bc. $parser->format($string);

*NB:* The string is passed to format() by reference and *the value is changed* by the parser.

h3. Setting transfomrations for all substitutions:

If you are formatting something that needs all the substitutions to be transformed in a certain manner you just...

bc. $parser->set('url', true);

p. ...and the parser will apply the transformation as it goes. You can set as many or few as needed.

h3. Putting it together:

You can format as many blocks as you want with a given parser & context...

bc.. $body = "Hi {firstname>title} and welcome to our service. You can login using your username {name} and password.";
$subject = "Welcome {name>1>title}"; // Show the first word of the name in title case.
$parser = wire()->modules->get("TextformatterTagParser");
->set('context', $user)
->set('email', true) // apply the email transformation to all substituted values in the subject to prevent header injections
->format($subject) // make $subject specific to this $user
->set('email', false) // no need to prevent headers in the body
->format($body) // make $body specific to given $user
$sent = @email($user->email, $subject, $body);

p. You can setup new contexts on a given parser instance between format() calls.

h3. Debug output

If you'd like to see a trail of which transformations were applied by the parser do a @$parser->set('debug', true)@ before you call @format()@.

h2. Spinning Alternate Texts

You can have the tag parser select from a set of alternative strings in your input using the following, regex-or like, syntax...

bc. "Dear {{mum|dad|friend}}, {{How are you|What have you been up to|What's your news}}?"

Spinning happens after contextual substitutions so you can include them in the spinning alternatives...

bc. "...since we saw you. {{Is your phone number still {user.phone}?|Are you still available on {user.phone}?|I think you let
your plan lapse.}}"

h3. Using HannaCode

HannaCode can really help define common alternative blocks that you might want to use repeatedly in your texts. For example, if you wanted to spin some adjectives about size you could setup HannaCode to run before the tag parser and use some substitutions such as...

bc.. big** => {{big|huge|massive|gigantic}}
small** => {{small|tiny|microscopic}}

p. ...and then say things like...

bc. "It was a big** event with a small** budget."

...and get results such as...

bc.. It was a huge event with a tiny budget.
It was a massive event with a microscopic budget.

h3. Controlling Randomness.

The tag parser allows you to control the degree of randomness used in selecting alternatives used in the spinning process. By default each choice is totally random -- every time you visit the page using the tag parser on a field you should see a different spin on the message. However, you can fix the result by setting the @spinkey@ to any integer you like. Once you do this, you will always get the same generated text. Alternatively, you can set the @spinkey@ to the value returned from the @$_SERVER[HTTP_REFERER]@ variable so that visitors from sites linking to your site get one spin and visitors coming in from elsewhere get a different spin. Please note that any querystring or fragment parts of the URL will influence the spinning of text too unless you pass the referrer URL through the parser's @UrlToKey()@ method first.

h2. Helper Module

There is a small "test module":https://github.com/netcarver/PW-ProcessTagParserTest available that allows you to experiment with this module from within a ProcessWire installation.

h2. License


Install and use modules at your own risk. Always have a site and database backup before installing new modules.

Twitter updates

  • ProcessWire 3.0.185 (dev) core updates, plus new Session Allow module— More
    17 September 2021
  • Three new ProcessWire Textformatter modules: Find/Replace, Markdown in Markup, and Emoji— More
    3 September 2021
  • This week we have a new master version released after a year in the making. With nearly 40 pull requests, hundreds of new additions and more than 100 issue reports resolved, this new version has a ton of great new stuff— More
    27 August 2021

Latest news

  • ProcessWire Weekly #385
    In the 385th issue of ProcessWire Weekly we'll cover the latest weekly update from Ryan, check out a new fieldtype module called Page Reference Context Data, and more. Read on!
    Weekly.pw / 25 September 2021
  • ProcessWire 3.0.184 new master/main version
    This week we have a new master/main version released after a full year in the making. As you might imagine, this new version has a ton of great new stuff and we’ll try to cover much of it here.
    Blog / 27 August 2021
  • Subscribe to weekly ProcessWire news

I just love the easy and intuitive ProcessWire API. ProcessWire rocks!” —Jens Martsch, Web developer