Jun 30, 2008

TYPO3 stdWrap explained

stdWrap is one of the most powerful and at the same time obscure TYPO3 functions. In these series of articles I am going to make this function more clear for both TypoScript and extension developers.

What is stdWrap?

stdWrap is a TYPO3 function that can alter data or replace it with completely another data if developer wishes so. stdWrap is incredibly powerful. It can do many transformations, check conditions, use content objects and many more. If there is no transformation that developer needs, it is always possible to extend stdWrap with a custom function.

A most simple example of stdWrap is:

temp.test = TEXT
temp.test {
  value = Hello, world!
  wrap = The boring phrase: "|"
}

This will produce the "Hello, world" prepended by "The boring phrase".

I am sure you used it wrap property a lot but have you realized that you actually used stdWrap?

Data and stdWrap

stdWrap is a function that processes data. It can obtain data in many ways. Often data is just passed to stdWrap (like in the example above). Sometimes data comes from the database record or can be generated by stdWrap itself.

Data and content

There is a concept of “data” and “content”. Content is passed to the stdWrap as input. “value” in the example above is such content. Data is stored inside content object, on which stdWrap is called. Consider the example:

temp.test = CONTENT
temp.test {
  select {
    selectFields = header
    uidInList = 5
  }
  table = tt_content
  renderObj = TEXT
  renderObj.field = header
}

Here there is the same TEXT object for rendering. But there is no content passed to stdWrap. Instead there is a “field” stdWrap property, which is set to “header”. This field refers to data in the TEXT content object. CONTENT will set record to TEXT's data and stdWrap will access it to extract “header” and return it back to TEXT. That's the difference between content and data in stdWrap. Content is a value and data is an array of fields.

“Current” value

“current” value is one of most obscure concepts in the stdWrap. “current” value is an additional special field in the current stdWrap data array. It cannot be accessed directly but there are several properties to manipulate “current” value.

The first property is “setContentToCurrent”. It is another confusing name in TYPO3. In reality it means that it sets “current” value to be the same as current content. In other words, content value is copied to “current” value. Example:

temp.test = TEXT
temp.test.value = Hello!
temp.test.setContentToCurrent = 1

In this example “current” value becomes “Hello!”. What is the use of this? You can operate the content of the current value using stdWrap. But we will come to it later.
The next property is “setCurrent”. It is a stdWrap itself and you can use it to set current value to whatever is produced by this stdWrap. You could do this, for example:

temp.test = TEXT
temp.test.setCurrent = Hello!

The last property in this group is “current”. It sets content to the value of “current” data field. Continuing previous example:

test.test.current = 1

The result of TEXT content object becomes “Hello!”. Of course, this example is pretty stupid because you just could use “value” property. But it shows how various properties interact.

“data”, “getText” and “dataWrap”

“data” property provides two levels of access:

  • access to the content object's data record
  • access to different PHP variables (such as $_GET), TSFE properties, registers, etc.

The “data” property is of “getText” type. Whenever you need access to something, which you cannot access with other properties, check “getText” in the TSRef. It is likely that you will find it.

Example of using “data” property:

temp.test = TEXT
temp.test.data = global : SERVER | HTTP_HOST

Another useful property is “dataWrap”. This one combines “data” and “wrap” into one thing. For example:

temp.test = TEXT
temp.test.dataWrap = My host is: {global : SERVER | HTTP_HOST}

You might thing that you can accomplish it with this:

temp.test = TEXT
temp.test.data = global : SERVER | HTTP_HOST
temp.test.wrap = My host is: |

Yes it work in this particular case. But if you add more stdWrap properties, you can get something modifying data in between the “data” and “wrap”. So “dataWrap” allows you to make it atomic: “data” and “wrap” powers at one step.

Different kind of wraps

Now let's take a look into different wrapping functions of stdWrap. We already saw two: “wrap” and “dataWrap”.

“wrap” takes a string with a pipe character in it. Everything before and after the pipe is trimmed and pipe is replaced with current content value. The important thing is to remember about trimming. This may produce unexpected result if you forget about trimming:

temp.test = TEXT
temp.test.value = apples
temp.test.wrap = I like | very much!

At the first glance all seems ok. Have you already forgot about trimming? As a result you will get:

I likeapplesvery much

How do you avoid it?

There are two ways. The first only is ugly:

temp.test.wrap = I like | very much!

It inserts space using HTML entities. Ugly but works. Better one is using yet another wrap, now non‑trimming:

temp.test.noTrimWrap = |I like | very much!|

The key thing here is extra pipes. Use that and nothing is trimmed.

The order of properties

stdWrap properties are always called in certain order. You have to take this into account when writing TypoScript. Fo example, “wrap” is called before “dataWrap”. If you use both and want general wrapping to happen after “dataWrap”, you will have to look up what goes after “datWrap” (the answer is “wrap3”).

Another example is “insertData”, which is used after “wrap3” and has effect of “dataWrap” on the current content:

temp.test = TEXT
temp.test {
  dataWrap = Your host is: “{global : _SERVER | REMOTE_HOST}”
  wrap = |, your address is {global : _SERVER | REMOTE_ADDR}
  insertData = 1
}

Combining it wraps and data gives TypoScript writer a lot of power to manipulate data.

This is only an short introductions to stdWrap. If you want to know its full power, make sure you read about stdWrap in TSRef.

1 comment:

  1. Hi Dimitry,

    Thanks for this post.
    Just a question, how can I write a pipe in my title ?
    The only way I found is page.headerData.1.wrap = < title > | x My site name

    Thanks

    ReplyDelete