Showing posts with label Symfony Console. Show all posts
Showing posts with label Symfony Console. Show all posts

Thursday, June 23, 2022

Using TYPO3 FluidEmail in CLI context

Since TYPO3 10.4 it is possible to use TYPO3\CMS\Core\Mail\FluidEmail to send emails with body content rendered by Fluid. This all works fine as long as you work in frontend or backend context, but when you use FluidEmail in CLI context (e.g. in a symfony console command), you will run into some problems. Since no real server request object is available, TYPO3 is not able to construct URIs using Fluid ViewHelpers nor will the Image ViewHelper render working absolute image links. Especially the last problem (non working website logo in rendered FluidEmail default template) motivated me to dig deeper into the topic. 

Below follows a summary of things you should consider when working with FluidEmail (or Fluid StandaloneView) in CLI context.

All Fluid ViewHelpers in the namespace f:uri or f:link do not work by default

The ViewHelpers depend on either a TypoScriptFrontendController object or the global TYPO3_REQUEST variable being available. Both are not in CLI context. 

One workaround for this problem is to create an instance of $GLOBALS['TYPO3_REQUEST'] manually in your symfony console command as shown below:


$site = GeneralUtility::makeInstance(SiteFinder::class)->getSiteByPageId(1);
$request = (new ServerRequest())
    ->withAttribute('applicationType', SystemEnvironmentBuilder::REQUESTTYPE_FE)
    ->withAttribute('site', $site);
$GLOBALS['TYPO3_REQUEST'] = $request;

Note, that the site object is fetched by the uid of page 1. This must be kept in mind, when you have a TYPO3 website with multiple sites defined.

Link created with f:link.action must always contain the extensionName

If the previous workaround is used, it is mandatory to set the "extensionName" argument in the f:link.action or f:uri.action ViewHelper.

Create links manually

An alternative to the previous example, where the $GLOBALS['TYPO3_REQUEST'] object is created manually, is to create all links manually used in the FluidEmail template in the symfony console command. This can done as shown below:


$arguments = [
    'tx_sfeventmgt_pieventdetail' => [
        'action' => 'detail',
        'controller' => 'Event',
        'event' => 25,
    ],
];

$site = GeneralUtility::makeInstance(SiteFinder::class)->getSiteByPageId(1);
$eventLink = (string)$site->getRouter()->generateUri(22, $arguments);

Note again, that the site object is fetched by the uid of page 1. The variable $eventLink can then be passed to the view and be used as href attribute for a-tags.

Image ViewHelper creates broken URLs

When you try to render an image with an absolute path using the f:image ViewHelper, the resulting link will be broken. Example:


<f:image absolute="1" src="EXT:sf_event_mgt/Resources/Public/Icons/Extension.svg" width="100" />

In CLI context this will create an img tag as shown below


<img src="http://./typo3/sysext/core/bin/typo3conf/ext/sf_event_mgt/Resources/Public/Icons/Extension.svg" width="100" height="104" alt="">

In order to create a workaround for the problem, I found 2 different approaches.

Workaround 1

FluidEmail has the function setRequest() which allows to set a ServerRequest object for the view. 


$site = GeneralUtility::makeInstance(SiteFinder::class)->getSiteByPageId(1);

$normalizedParams = new NormalizedParams(
    [
        'HTTP_HOST' => $site->getBase()->getHost(),
        'HTTPS' => $site->getBase()->getScheme() === 'https' ? 'on' : 'off',
    ],
    $systemConfiguration ?? $GLOBALS['TYPO3_CONF_VARS']['SYS'],
    '',
    ''
);

$request = (new ServerRequest())
    ->withAttribute('applicationType', SystemEnvironmentBuilder::REQUESTTYPE_FE)
    ->withAttribute('normalizedParams', $normalizedParams)
    ->withAttribute('site', $site);
    
$email->setRequest($request);

By assigning the request object to the view, the variable {normalizedParams.siteUrl} is now also available in CLI context resulting in the TYPO3 logo being shown again in the default email layout. 

Workaround 2

The f:image ViewHelper will create relative links to images when the argument "absolute" is not used. So basically just the baseUri is missing. In the previous workaround {normalizedParams.siteUrl} was used to add the baseUri, but instead it is also possible to assign the sites baseUri as Fluid variable as shown below:


$site = GeneralUtility::makeInstance(SiteFinder::class)->getSiteByPageId(1);
$email->assign('baseUri', (string)$site->getBase());

In the template the full path to the image can now be created as following:


<img src="{baseUri}{f:uri.image(src: 'EXT:sf_event_mgt/Resources/Public/Icons/Extension.svg', width: '100')}" width="100" />

Ensure to set the correct application context in CLI

Whenever the site object is fetched using the SiteFinder, the resulting base is resolved respecting TYPO3s application context. By default this is "production". If you e.g. have a testing or staging environment and use one of the described workarounds, ensure to set the application context as environment variable as shown below:

export TYPO3_CONTEXT=Development


Friday, November 22, 2019

TYPO3 Extension "Plain FAQ" released

Today I released the first public version of my latest TYPO3 Extension called "Plain FAQ". The name already says it - the extension is a very simple solution to manage Frequently Asked Questions in TYPO3. Below follow some of the facts about the Extension:
  • Compatible with TYPO3 8.7 and 9.5
  • Based on Extbase and Fluid
  • Covered with unit and functional tests
  • Easy usage for editors
  • Uses TYPO3 system categories to structure FAQs by category
  • Field for media and files
  • Possibility to add related FAQs
  • Configurable template layouts for the views
  • Automatic cache cleanup when a FAQ article has been updated in backend
  • Signal slots to extend the extension with own functionality
  • Symfony Console commands to migrate from ext:irfaq
The extension is available on TER and packagist.

Migration from "Modern FAQ (irfaq)"

If you currently use the TYPO3 Extension "Modern FAQ (irfaq)" you may have noticed, that the extension is not compatible to TYPO3 9.5 (last Extension-Update in March 2018)  and the architecture is quite old (AbstractPlugin, Marker Based Templates and TypoScript configuration for wraps). 

For users where "Modern FAQ (irfaq)" is a blocker for an upcoming TYPO3 9.5 Update, it is possible to migrate to "Plain FAQ" using the Symfony Console Commands included in "Plain FAQ". The migration is as easy as the usage of the extension:

1. Migrate existing Categories to sys_category
2. Migrate existing FAQs to "plain_faq" records
3. Migrate existing Plugins including Plugin settings

The migration may not cover all possible scenarios (e.g. Ratings, Question asked by, irfaq Plugin settings set by TypoScript), but is for sure a good starting point in order to migrate existing records. I guess, for most websites the included migration will suite without further work on migrated data.

You can find details about the migration process in the Extension Manual.

Thanks for sponsoring


I would like to thank Julius-Maximilians-Universität Würzburg for sponsoring the initial development of the TYPO3 extension. Thanks for supporting TYPO3 and open source software!