> For the complete documentation index, see [llms.txt](https://playground.e107sk.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://playground.e107sk.com/plugin-dev-quick-notes/how-to-1/template-wrappers-leak-into-later-output-never-reuse-the-same-shortcode-text.md).

# Template wrappers leak into later output: never reuse the same shortcode text

### Symptom

You add a wrapper for a shortcode in one template, for example in `page_template.php`:

```php
$PAGE_WRAPPER['contact']['THEME_CONTACT_PREF: type=organization'] = '<h2 class="h4">{---}</h2>';
```

It works on the page. But on that page **the same shortcode somewhere else** (typically in the footer) suddenly gets the same HTML around it. On pages that use another template, the footer looks normal.

Only shortcodes written **exactly the same way** are affected. For example, `{THEME_CONTACT_PREF: type=address}` in both the page template and the footer is affected. `{THEME_CONTACT_PREF: type=phone1&format=link}` on the page and `{THEME_CONTACT_PREF: type=phone1}` in the footer are not.

### Why it happens

Verified in the e107 source (`e107_handlers/shortcode_handler.php`, e107 master):

1. The page sets a wrapper ID on its shortcode batch (`page.php` calls `->wrapper('page/<template>')`).
2. When the parser receives that batch, it **adds** the wrappers of that ID into its own list (`$this->wrappers`, `array_merge`, in `parseCodes()`).
3. The parser is **one shared object for the whole request**. After the page content is parsed, the list is **not cleared**. It is only reset when a later batch has a wrapper ID but no wrappers of its own.
4. The footer is parsed after the page. When a shortcode is rendered, `makeWrapper()` looks up a wrapper by the **full shortcode text** (name + parameters). If the footer contains the same text, it finds the page wrapper and uses it.

So a wrapper is not limited to the template where you defined it. It stays active for the rest of the request.

### Fix: make the shortcode text unique

Give the shortcode in the template an extra parameter that the shortcode ignores. Use it in **both** places: the wrapper key and the template body. They must match character by character.

```php
$PAGE_WRAPPER['contact']['THEME_CONTACT_PREF: type=organization&ctx=page'] = '<h2 class="h4">{---}</h2>';
```

```
{THEME_CONTACT_PREF: type=organization&ctx=page}
```

The footer keeps `{THEME_CONTACT_PREF: type=organization}`. The texts differ, so the footer gets no wrapper.

**Before you do this, read the shortcode code.** The extra parameter is safe only if the shortcode ignores parameters it does not know. A shortcode that reads only `$parm['type']` and `$parm['format']` is fine. A shortcode that, for example, builds a URL from all parameters is not.

Name the parameter after the place where it is used (`ctx=page`, `ctx=contact`), so it is clear why it is there. Add a one-line comment above the wrappers, because the next person will want to "clean it up".

### Alternatives (not recommended)

**Put the HTML into the template body instead of a wrapper.** Wrappers are useful because an empty value prints nothing, including its heading. Without a wrapper, a heading appears even when the value is empty.

**Clear the parser's wrappers before the footer (in `theme.php`).** This changes internal state of the core parser. It can break with any core update.

### Checklist when adding a wrapper

* Search the whole theme for the same shortcode text: layouts, `header_*.html`, `footer_*.html`, `elements/*.html`, other templates, menus.
* If the text appears anywhere else, add a context parameter (`&ctx=...`) to the templated version.
* Check that the shortcode ignores the extra parameter.
* Test a page that uses the template **and** a page that does not. Check the header and the footer on both.
