TinyButStrong - the PHP Template Engine
Categories > TinyButStrong general >

[TBS] List all merge fields and merge blocks

The forum is closed. Please use Stack Overflow for submitting new questions. Use tags: tinybutstrong , opentbs

By: GnsBeldaran
Date: 2014-02-18
Time: 16:51

[TBS] List all merge fields and merge blocks


For the purpose of my application using a lot of templates (about a thousand), I need to be able to find all the merge fields (and especially all the blocks and their fields).
I started by parsing the attribute Source of my TBS object with a lot of regex to catch all the [XXX] string inside but that seems just wrong.

Does the TBS object have a public method I can call to list all the blocks and fields ? Or is there a snippet anywhere that does the job in a good way ?
It would be great if the parameters of the fields (especially the 'when ... ' parts) were provided too

Sincerely yours,


PS : I am using the latest versions of TBS and OpenTBS as of 2014-02-18 (the templates are .docx files)
By: Skrol29
Date: 2014-02-18
Time: 18:39

Re: [TBS] List all merge fields and merge blocks

Hi GnsBeldaran,

TBS has an internal feature for listing blocks and fields staring for a knowed name.

Unfortunately there is no feature for finding blocks or fields for names that you don't already know.
BUT if you write a function that returns a list of possible names (for example by searching "[" and then ";" or "." or "]" ) then you can use the internal function for those names. Erroneous names will makes the internal functions to return an negative result but not an error.
By: GnsBeldaran
Date: 2014-02-19
Time: 09:16

Re: [TBS] List all merge fields and merge blocks

Hi Skrol29,
Thank you for your answer,

Unfortunately my application stands between the templates and a bunch of views (about two hundreds) in the database.
It is supposed to find the template, list all fields and blocks in it, find a maximum of data in the DB and let the user fill the entries it didn't find.

It works well for now, but I am scared that my way to find them isn't sustainable
(I mean, I list all the fields with something like /(\\[(?>[^\\[\\]]+|((?1)))\\])/imsx, (I preg_quote the open and close tags) and then do a lot of jobs in it to find conditionnal fields etc...)

Well I hope there will be in future some parser or something to let you list those fields :)

Thank you a lot,

By: Skrol29
Date: 2014-02-19
Time: 23:11

Re: [TBS] List all merge fields and merge blocks

Can your explain your regexp ?
By: Sheepy
Date: 2014-02-26
Time: 09:53

Re: [TBS] List all merge fields and merge blocks

Hi GnsBeldaran,

It's essentially impossible to accurately deduce all unmerged tags.  You can have "[a][b]" and says $tbs->MergeField( "a][b", "[c]" ).

However, it is possible to detect a subset of them using regx.  I have difficulty applying the one you provided, so here is my example:

$matches = [];
preg_match_all( '~    # pattern to match TBS tag
                 \[   # start tag
                 ([^;.\]]+) # first tag part ("var" in [var.a.b])
                 ([^;\]]*)  # remaining tag part (".a.b" in [var.a.b])
                 (              # start options capture group,
                   (?:          # which is a collection of...
                     \[val\]       # [val]
                    |\'[^\']*\'    # single quoted values
                    |"[^"]*"       # double quoted values
                    |[^\[\]]+      # any non-tag characters
                  )             # close options capture group
                 \s*\]?  # end tag.
                 ~Sx', $tbs->Source, $matches );
$open_tags = array_unique( $matches[1] ); // returns ['a','b']

Hope this pattern is easier to read and modify.  To go further may require a real parser like TBS.

By: GnsBeldaran
Date: 2014-02-26
Time: 10:21

Re: [TBS] List all merge fields and merge blocks

Hey there,
I am sorry Skrol29, I didnt see your reply.

My regex was parsing the source to find all the square braces in the source : for example, if I have '[a.label][a.[b.colKey]]', it would return me ['[a.label'], '[a.[b.colKey]]', '[b.colKey]'].
But I have like 5 other regexes that I can't legally disclose that makes sure that at the end I have an array like this one :
['blockName' => ['val1', 'val2', ....']] (in my example it would be ['a' => ['label'], 'b' => ['colKey']]

There are some blockNames that are now reserved :
* 'choices' : block created after the parsing of the source to find all the [...;block=begin when [x] = 1] XXX [...;block=end] in order to know what is the paragraph conditionnaly displayed so I can have some radio buttons to let the user choose
* 'user' : user-related data (like his email, phonenumber, job, etc...) that are stored in the database
* 'entries' : data that have to be fill by the user (in a form)