Skip to content

Commit 14027d2

Browse files
authored
docs: place template-override settings inside preUserFunc. (#845)
## Summary The current template-override documentation places `settings.templateRootPaths` as a **sibling** of `preUserFunc` under `lib.parseFunc_RTE.tags.img`, e.g. (from `Documentation/Examples/Template-Overrides.rst`): ```typoscript lib.parseFunc_RTE.tags.img { settings.templateRootPaths { 10 = EXT:my_sitepackage/Resources/Private/Templates/ } } ``` That placement has no effect. TYPO3's `ContentObjectRenderer::stdWrap_preUserFunc()` only forwards `$conf['preUserFunc.']` to the callable: ```php // typo3/cms-frontend Classes/ContentObject/ContentObjectRenderer.php public function stdWrap_preUserFunc($content = '', $conf = []) { return $this->callUserFunction($conf['preUserFunc'], $conf['preUserFunc.'] ?? [], $content); } ``` So anything under `tags.img.settings.*` is never seen by `ImageRenderingAdapter::renderImageAttributes()`, and therefore never reaches `ImageRenderingService::buildTemplatePaths()`. As written today, the documented override silently does nothing — integrators end up with the default extension templates regardless of what `templateRootPaths` they set. The correct placement is **inside** `preUserFunc.`: ```typoscript lib.parseFunc_RTE.tags.img.preUserFunc { settings.templateRootPaths { 10 = EXT:my_sitepackage/Resources/Private/Templates/ } } ``` The same applies to `externalBlocks.figure.stdWrap.preUserFunc` for figure-wrapped (captioned) images, which is rendered via `renderFigure()`. ## Empirical confirmation I hit this while overriding templates in my own site package: with `settings.*` at the documented `tags.img` level my custom templates were ignored. After moving the block into `preUserFunc.settings.*`, the custom templates loaded immediately. ImageRenderingService's `buildTemplatePaths()` already handles either `$config['settings.']['templateRootPaths.']` or `$config['templateRootPaths.']` directly, so the only change needed is in the docs. ## Changes Three places carried the same incorrect example; this PR fixes all three: - `Documentation/Examples/Template-Overrides.rst` — the canonical override example, plus the accompanying note about `externalBlocks.figure.stdWrap`. The figure-side example is now spelled out explicitly so users don't have to guess where to put it. - `Resources/AGENTS.md` — short architectural note that mirrored the bad example. - `Configuration/TypoScript/ImageRendering/setup.typoscript` — inline comment block that shipped with the extension. Each fix moves `settings.*` under `preUserFunc.` and adds a one-line explanation of *why* (`stdWrap_preUserFunc` only forwards its own sub-array), so future readers don't have to re-trace the call. ## Test plan - [x] Pre-commit hooks pass (`make lint`) — docs-only change, no PHP/JS edits. - [x] Unit tests pass (`composer ci:test:php:unit`) — docs-only change. - [x] Manual testing performed — verified that moving `settings.templateRootPaths` under `preUserFunc.` is the placement that actually loads custom templates on a real TYPO3 v13.10 install. ## Related issues <!-- No matching open issue found; happy to file one if the maintainers prefer that flow. -->
2 parents 1ad5a91 + fab386f commit 14027d2

3 files changed

Lines changed: 84 additions & 32 deletions

File tree

Configuration/TypoScript/ImageRendering/setup.typoscript

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,29 @@ lib.parseFunc_RTE {
2525
# IMPORTANT: Use the extension key "rte_ckeditor_image" (underscores) in
2626
# EXT: paths, NOT the Composer package name "rte-ckeditor-image" (hyphens).
2727
#
28-
# To override, add your paths with priority > 0:
28+
# To override, add your paths with priority > 0 INSIDE preUserFunc. —
29+
# TYPO3's stdWrap_preUserFunc only forwards $conf['preUserFunc.'] to the
30+
# callable, so a settings. block placed as a sibling of preUserFunc
31+
# never reaches ImageRenderingService::buildTemplatePaths().
2932
#
30-
# settings.templateRootPaths {
31-
# 10 = EXT:my_sitepackage/Resources/Private/Templates/
32-
# }
33-
# settings.partialRootPaths {
34-
# 10 = EXT:my_sitepackage/Resources/Private/Partials/
35-
# }
36-
# settings.layoutRootPaths {
37-
# 10 = EXT:my_sitepackage/Resources/Private/Layouts/
33+
# preUserFunc {
34+
# settings {
35+
# templateRootPaths {
36+
# 10 = EXT:my_sitepackage/Resources/Private/Templates/
37+
# }
38+
# partialRootPaths {
39+
# 10 = EXT:my_sitepackage/Resources/Private/Partials/
40+
# }
41+
# layoutRootPaths {
42+
# 10 = EXT:my_sitepackage/Resources/Private/Layouts/
43+
# }
44+
# }
3845
# }
3946
#
47+
# The same settings. block must also be added under
48+
# lib.parseFunc_RTE.externalBlocks.figure.stdWrap.preUserFunc for
49+
# captioned (figure-wrapped) images.
50+
#
4051
# See Documentation/Examples/Template-Overrides.rst for details.
4152
#******************************************************
4253

Documentation/Examples/Template-Overrides.rst

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -190,34 +190,57 @@ In your site package, create the override directory:
190190
Step 2: Configure TypoScript
191191
----------------------------
192192

193-
Add the template path to your TypoScript setup:
193+
Add the template path to your TypoScript setup. The ``settings.`` block
194+
must live **inside** ``preUserFunc.`` — that is the only sub-array TYPO3
195+
forwards to the rendering callable (see
196+
:php:`ContentObjectRenderer::stdWrap_preUserFunc()`, which passes only
197+
``$conf['preUserFunc.']`` to the user function). Placing
198+
``settings.templateRootPaths`` as a sibling of ``preUserFunc`` has no
199+
effect — the configuration never reaches
200+
:php:`ImageRenderingService::buildTemplatePaths()`.
194201

195202
.. code-block:: typoscript
196203
:caption: EXT:my_sitepackage/Configuration/TypoScript/setup.typoscript
197204
198-
lib.parseFunc_RTE.tags.img {
205+
lib.parseFunc_RTE.tags.img.preUserFunc {
199206
# Add your templates with higher priority (higher number = higher priority)
200-
settings.templateRootPaths {
201-
10 = EXT:my_sitepackage/Resources/Private/Templates/
207+
settings {
208+
templateRootPaths {
209+
10 = EXT:my_sitepackage/Resources/Private/Templates/
210+
}
211+
partialRootPaths {
212+
10 = EXT:my_sitepackage/Resources/Private/Partials/
213+
}
214+
layoutRootPaths {
215+
10 = EXT:my_sitepackage/Resources/Private/Layouts/
216+
}
202217
}
203-
settings.partialRootPaths {
204-
10 = EXT:my_sitepackage/Resources/Private/Partials/
205-
}
206-
settings.layoutRootPaths {
207-
10 = EXT:my_sitepackage/Resources/Private/Layouts/
218+
}
219+
220+
# Captioned images render as <figure> blocks and are processed via
221+
# externalBlocks.figure.stdWrap.preUserFunc (renderFigure). The same
222+
# settings. block has to be duplicated here for figure rendering.
223+
lib.parseFunc_RTE.externalBlocks.figure.stdWrap.preUserFunc {
224+
settings {
225+
templateRootPaths {
226+
10 = EXT:my_sitepackage/Resources/Private/Templates/
227+
}
228+
partialRootPaths {
229+
10 = EXT:my_sitepackage/Resources/Private/Partials/
230+
}
231+
layoutRootPaths {
232+
10 = EXT:my_sitepackage/Resources/Private/Layouts/
233+
}
208234
}
209235
}
210236
211237
.. note::
212238

213-
The configuration must be placed within ``lib.parseFunc_RTE.tags.img``
214-
(not directly in ``lib.parseFunc_RTE``). The same configuration can be
215-
added to ``externalBlocks.figure.stdWrap`` for images wrapped in
216-
``<figure>`` blocks (captioned images). Figures are processed via
217-
``externalBlocks``, not ``tags.figure`` — placing the configuration
218-
under ``tags.figure`` has no effect. Inline images wrapped in ``<a>``
219-
are rendered by ``tags.img`` (recursively, inside the link wrapper), so
220-
they already pick up the configuration defined under ``tags.img``.
239+
Figures are processed via ``externalBlocks``, not ``tags.figure`` —
240+
placing the configuration under ``tags.figure`` has no effect. Inline
241+
images wrapped in ``<a>`` are rendered by ``tags.img`` (recursively,
242+
inside the link wrapper), so they already pick up the configuration
243+
defined under ``tags.img.preUserFunc``.
221244

222245
Step 3: Create override templates
223246
---------------------------------

Resources/AGENTS.md

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,33 @@ Figure wrappers are only created when there is a caption. Alignment classes with
6666

6767
## Template Override Mechanism
6868

69-
Integrators can override templates via TypoScript:
69+
Integrators can override templates via TypoScript. The `settings.` block
70+
must live inside `preUserFunc.` because TYPO3 only passes
71+
`$conf['preUserFunc.']` to the rendering callable (see
72+
`ContentObjectRenderer::stdWrap_preUserFunc()`):
7073

7174
```typoscript
72-
lib.parseFunc_RTE.tags.img {
73-
settings.templateRootPaths {
74-
10 = EXT:my_sitepackage/Resources/Private/Templates/
75+
lib.parseFunc_RTE.tags.img.preUserFunc {
76+
settings {
77+
templateRootPaths {
78+
10 = EXT:my_sitepackage/Resources/Private/Templates/
79+
}
80+
partialRootPaths {
81+
10 = EXT:my_sitepackage/Resources/Private/Partials/
82+
}
7583
}
76-
settings.partialRootPaths {
77-
10 = EXT:my_sitepackage/Resources/Private/Partials/
84+
}
85+
86+
# Figures (captioned images) need the same block under the
87+
# externalBlocks.figure.stdWrap.preUserFunc that runs renderFigure().
88+
lib.parseFunc_RTE.externalBlocks.figure.stdWrap.preUserFunc {
89+
settings {
90+
templateRootPaths {
91+
10 = EXT:my_sitepackage/Resources/Private/Templates/
92+
}
93+
partialRootPaths {
94+
10 = EXT:my_sitepackage/Resources/Private/Partials/
95+
}
7896
}
7997
}
8098
```

0 commit comments

Comments
 (0)