If I extend a core template in my theme (blocks.mustache for example), how can I output theme data inside it?
I've added the template to: theme_name/templates/core/blocks.mustache and I've tried adding a simple variable with the site name but it outputs no data.
Is there any way of doing this without extending the renderer?
If you just want to override parent theme templates inside your extended child theme then:
Create a folder in your theme folder name {yourtheme}/templates/theme_{parent_theme_name} (e.g. if you extended boost create a folder at {yourtheme}/templates/theme_boost
Copy the mustache file you want to override from the parent theme into this folder. (e.g. if you are extending boost and you want to override header.mustache, then copy theme/boost/templates/header.mustache to theme/{yourtheme}/templates/theme_boost/header.mustache and then edit it)
Edit: I did not see the part about not extending the renderer. I have left the answer for other users looking for a solution involving a renderer.
You will need to create a custom core renderer that extends the core_renderer. Then re-create (copy from core_renderer class) the function block(block_contents $bc, $region)
You can then assign a variable to the $data there and it would be available in the template.
class theme_yourthemename_core_renderer extends core_renderer {
...
public function block(block_contents $bc, $region) {
$this->init_block_hider_js($bc);
$data = \core\output\block::from_block_contents($bc, $this);
// Your code here
$data->yourvar = 'Some val'
return $this->render_from_template('core/block', $data);
}
}
Related
I wanted to ask if in TYPO3 LTS 11 is a way to change how TYPO3 generates the name for a rendered image?
In the template I use the f:image Viewhelper with cropVariant option to generates the image (done by TYPO3 Image Rendering).
<f:image image="{file}" cropVariant="desktop" />
That Image then has a name something like this: csm_my-image_88ade60319.jpg
Can I define how TYPO3 should name those rendered images?
For example to "my-image_large.jpg"
The cms_ part of the filename is hardcoded in the TYPO3\CMS\Core\Resource\Processing\ImageCropScaleMaskTask::getTargetFileName function. The hash at the end is added in the TYPO3\CMS\Core\Resource\Processing\AbstractGraphicalTask::getTargetFileName function. Not sure why cms_ is added, but the hash is to make sure the file name is unique. The hash is generated using the file and configuration.
So by default it isn't possible. If you really want different file names you can XCLASS TYPO3\CMS\Core\Resource\Processing\ImageCropScaleMaskTask with something like:
<?php
namespace Vendor\MyExtension\Resource\Processing;
class ImageCropScaleMaskTask extends \TYPO3\CMS\Core\Resource\Processing\ImageCropScaleMaskTask
{
public function getTargetFileName()
{
$originalFileName = parent::getTargetFilename();
$fancyFileName = ... // Do your things to change the file name
return $fancyFileName;
}
}
You'll probably also want to add something to configure what the file name should be. So you'd probably also need to XCLASS the TYPO3\CMS\Fluid\ViewHelpers\ImageViewHelper class or create a new ViewHelper to add some settings to the processing instructions.
Just make sure the file name is unique or you might get weird results.
I have a TYPO3 website that is built on a sitepackage that extends bootstrap_package. I need to add more templates and design changes to the sitepackage, so I created a new extension. When I want to override the templates from sitepackage with the templates from my new extension, they all get overridden, and I get errors on the pages that used templates from the sitepackage.
Is there a way to load all templates, from the initial bootstrap_package, my sitepackage, and the new extension?
This is from the constants.txt of the sitepackage (example_theme), where it extends bootstrap_package:
constants.txt of the sitepackage example_theme ,
and this is how I am trying to override it with my new extension: constants.typoscript of my new extension
and setup.txt of the sitepackage example_theme
If I do this, then in the backend I can see that example_theme is not loaded:
backend setup
The pages that used templates from the sitepackage example_theme give me this error:
error on pages that use templates from example_theme
Either you have the wrong loading order of the extensions, or there is an extension not loaded.
Especially if you use only constants to define the paths you will miss a definition as only one constant (per path) is inserted.
In your case you should not use constants in your extension new_extension but set the value 2 in the setup immediately.
page {
10 {
TemplateRootPaths.2 = EXT:new_extension\Resources\Private\Templates\Page\
PartialRootPaths.2 = EXT:new_extension\Resources\Private\Partials\Page\
LayoutRootPaths.2 = EXT:new_extension\Resources\Private\Layouts\Page\
}
}
in this way you should end up with 3 values for each path.
(example just for templates:)
:
[templateRootPaths]
[0] = EXT:bootstrap_package\Resources\Private\Templates\Page\
[1] = EXT:example_theme\Resources\Private\Templates\Page\
[2] = EXT:new_extension\Resources\Private\Templates\Page\
Using the infos in this link:
https://docs.typo3.org/typo3cms/ExtbaseFluidBook/8-Fluid/9-using-php-based-views.html
I try to create an action to output a JSON.
I have a normal controller with the list action:
public function listAction()
{
$storelocators = $this->storelocatorRepository->findAll();
$this->view->assign('storelocators', $storelocators);
}
And in ext/my_storelocator/Classes/View/Storelocator I have a class List.php:
<?
class Tx_MyStorelocator_View_Storelocator_List extends Tx_Extbase_MVC_View_AbstractView {
public function render() {
return 'Hello World';
}
}
All I get is:
Sorry, the requested view was not found.
The technical reason is: No template was found. View could not be resolved for action "list" in class "My\MyStorelocator\Controller\StorelocatorController".
So I guess there is something wrong with the paths. Or where is the Problem?
Edit: Extensioninfos
Vendor: My
key: my_storelocator
controller: NOT SURE (I created it with the extension_builder so I guess my controllers name is Storelocator)
action: list
From my understanding a classname like Tx_MyStorelocator_View_Storelocator_List should be correct. But its not working
You will need to create an empty file for the HTML view for your controller, e.g. Resources/Private/Template/Storelocator/List.html, even if you do not plan to use the HTML view or if you just return the content yourself (which is perfectly fine).
The reason for this is simply technical limitation.
First of all, TYPO3 now has a built-in JSON view, described thoroughly here: https://usetypo3.com/json-view.html. It lets you easily define which properties you'd like to render.
The error message means that your Controller is still pointing to the TemplateView - because thats the error the TemplateView throws if it can't find the defined template file.
You can specify which view to use to render within your controller. You can either set a default view via the $defaultViewObjectName property, like so:
/**
* #var string
*/
protected $defaultViewObjectName = '\TYPO3\CMS\Fluid\View\TemplateView';
You can also set it from within the Controller inside initialization actions like so:
public function initializeExportPDFAction(){
$this->defaultViewObjectName = 'Vendor\Extension\View\FileTransferView';
}
(I have, however, not yet found a way to define the template from within actions, any tips in the comments would be appreciated)
Your path syntax is probably out of date. Instead of writing a render() function in Classes/View/Storelocator/List.php, try writing a listAction() function in a Classes/Controller/StorelocatorController.php file. Extension Builder should have created this file for you, if you made an aggregate model with the usual "list, create, edit ..." and such actions.
Review A journey through the Blog Example and the following chapter, Creating a first extension, for tips.
Keep in mind that there is a mismatch between the documentation and the Extension Builder generated PHP code files. Developing TYPO3 Extensions with Extbase and Fluid has some parts up to date, and other parts still using old syntax.
I'm using FPDI & FPDF to overlay new text on top of an existing PDF. It uses the useTemplate() method to achieve this.
Problem I'm having - it only applies the template to the first page. If the text is long, it will wrap to a second page, using the SetAutoPageBreak() method. How can I make it apply the template on every page?
I've cracked it. Looking into the code, I realised that even the SetAutoPageBreak() routine calls AddPage() internally, giving me the hook I needed to include my template on every page.
So, I extended the base FPDI class and over-rode the AddPage() method, including the useTemplate() stuff.
class BBPDF extends FPDI {
function AddPage($orientation='', $size='') {
parent::AddPage($orientation,$size);
$this->setSourceFile('templates/discover-community.pdf');
$template = $this->ImportPage(1);
$this->useTemplate($template);
}
}
Generating a mail message in a partial, I use the placeholder view-helper as follows:
<?php $this->placeholder('mykey')->startCapture() ?>
Some content here that is actually more complicated than just text.
Trust me that, in this case the, using the placeholder for capturing
is desirable.
<?php
$this->placeholder('mykey')->endCapture();
echo $this->placeholder('mykey');
?>
The problem is that if I use the same key in a different partial for a different mail message within the same request, then this captured content is still stored in the container for that key. In principle, I'd like the partials to be free to use whatever placeholder keys they want without having to sweat what other partials are using.
I know I can use different keys in different partials. Alternatively, I can manually clear the content after use/display with something like:
$this->placeholder('mykey')->set('');
But I'd hate to put the burden of all that on the view script that uses the placeholder.
I suspect what I want to do is create my own custom placeholder view-helper that auto-clears his captured content after it has been output.
I've tried creating a custom placeholder container (extends the Standalone container, overriding the toString() method), creating a custom view-helper (extends the the standard Placeholder view-helper), and telling the view-helper to use the custom container class.
But I keep bumping into some error associated to a missing view object. Clearly, I'm missing something about the how the view object, the container, and the registry all interact - and probably even something how the plugin system loads them all.
Any advice and general explanation greatly appreciated.
You need to set this container in the Placeholder view helper because otherwise the Zend_View_Helper_Placeholder_Registry loads automatically the Zend_View_Helper_Placeholder_Container. So, first you need to set your custom container manually. In a view script:
$this->getHelper('placeholder')
->getRegistry()
->setContainerClass('My_View_Helper_Placeholder_Container');
Or for exameple in a _initCustomContainer() in your Bootstrap.php:
$view = $this->bootstrap('view')->getResource('view');
$view->getHelper('placeholder')
->getRegistry()
->setContainerClass('My_View_Helper_Placeholder_Container');
Then, you need to create this class based on the Zend_View_Helper_Placeholder_Container (and not the Zend_View_Helper_Placeholder_Container_Standalone. I'd suggest you keep the option open to reset the content or not, you do that with a setter:
class My_View_Helper_Placeholder_Container
extends Zend_View_Helper_Placeholder_Container
{
protected $_resetCapture = true; // defaults true for new behaviour
public function setResetCapture($flag)
{
$this->_resetCapture = (bool) $flag;
return $this;
}
public function toString($indent = null)
{
$return = parent::toString($indent);
if ($this->_resetCapture) {
$this->exchangeArray(array());
}
return $return;
}
}
By default, the reset capture is already on, but to switch it off and start capturing:
$this->placeholder('my_key')->setResetCapture(false)->startCapture();
And to switch it on again:
$this->placeholder('my_key')->setResetCapture(true);
In a view script, use:
$this->placeholder('mykey')->captureStart('SET');
or using the class constant:
$this->placeholder('mykey')->captureStart(Zend_View_Helper_Placeholder_Container_Abstract::SET);