Using Fluid StandaloneView (also FluidMail) in CLI context - typo3

The name and description of StandaloneView ("Should be used as view if you want to use Fluid without Extbase extensions") suggests, that it is possible to use this view anywhere outside of any Extbase context. E.g. for CLI tasks such as generating emails (FluidMail) or using the view to generate HTML code which is than transformed into a PDF.
Unfortunately none of the above works if the template references assets such as images or CSS/JS files.
The reason is, that the view relys on a request-object to derive the domain-relative paths to the assets, which is obviously not working in CLI as no proper request-object exists:
TYPO3\CMS\Extbase\Mvc\Web\Request prototype object
format => protected "html" (4 chars)
pluginName => protected "" (0 chars)
controllerExtensionName => protected NULL
controllerSubpackageKey => protected NULL
controllerObjectName => protected "" (0 chars)
controllerName => protected "Standard" (8 chars)
controllerActionName => protected "index" (5 chars)
arguments => protected array(empty)
internalArguments => protected array(empty)
dispatched => protected FALSE
originalRequest => protected NULL
originalRequestMappingResults => protected NULL
method => protected "GET" (3 chars)
requestUri => protected "http:///var/www/html/vendor/bin/typo3cms" (40 chars)
baseUri => protected "http:///va/typo3/" (17 chars)
isCached => protected FALSE
The view-helper will create wrong URIs like this:
// f:uri.resource(path:'Css/pdf.css', extensionName: 'myext')
<link href="typo3conf/ext/myext/Resources/Public/Css/pdf.css" rel="stylesheet" />
// f:image(src:'EXT:myext/Resources/Public/Images/logo.png')
<img src="/va/typo3conf/ext/myext/Resources/Public/Images/logo.png" />
The solution given in here does not help, as the template file is rendered/found, but the linked assets are missing which messes up the template completely.
What is a possible solution for this issue? Or: how to work with the StandaloneView in a proper way? Since even the core FluidMail has this issue, it seems to be a general conceptional problem.
Appreciate any input, idea or solution!
PS:
To embed any recourses into the template is no solution!

For people having the same issue und looking for a solution I'll sum up what I already had in mind and what was confirmend by Julian (thanks). If anyone comes up with a better solution, feel free and apprechiated to share.
Solution 1: avoid linking of assets in templates which should be used in CLI contexts and embed all the needed resources inside the template.
Solution 2: faking a ServerRequest with a domain, to allow the ViewHelpers to determine the correct paths for liked assets.
Solution 3: using the BaseUrl helper function of base-url extension
Solution 4: write custom ViewHelpers (or better extending the common ones) which determine the paths to assets not only from the request object, but from the TYPO3 instance path if running as CLI, which should be enough for internal processing.
Still, the name StandaloneView is pretty missleading IMO concidering all the unexpected trouble using it e.g. in CLI context.

Related

How to change the position of a column in the TYPO3 TCA?

I want to move a column from one tab to another. Is there a better way than to rewrite the types definition manually which is not very reliant in regard to extension updates changing the TCA?
It's not 100% fail safe, since there still might be extensions messing things up, but the closest you can get will be to make use of the ExtTablesInclusionPostProcessing event and put addToAllTCAtypes into the invoke method, since this will not just add new fields but even put existing fields to another tab:
<?php
declare(strict_types=1);
namespace Vendor\Extension\EventListener;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
/**
* Class ExtTablesInclusionPostProcessing
*/
class ExtTablesInclusionPostProcessing
{
/**
* Function which may process data created / registered by extTables
* scripts (f.e. modifying TCA data of all extensions)
*
* #param AfterTcaCompilationEvent $event
*/
public function __invoke(AfterTcaCompilationEvent $event): void
{
ExtensionManagementUtility::addToAllTCAtypes('tt_content', 'fieldname', '', 'after:fieldname_in_the_other_tab');
}
}
To remove the existing field before, you could make use of this trick:
https://stackoverflow.com/a/59179916/2333754
And finally to be on the safer side you could make sure that other extensions are loaded before your own extension by putting them into the suggest section of your composer.json.
With installation of extension tcabuilder it is possible to do simple changes in the TCA.

TYPO3 extbase: Simple readable GET parameters

GET and POST parameters in custom extbase controllers need to be prefixed with the plugin signature to be injected automatically:
<?php
namespace Vendor\Example\Controller;
class SearchController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController
{
public function resultsAction($q = null)
{
//...
}
}
Search term $q is only filled automatically if it is passed as ?tx_example_search[q]=foo.
Is there a way declare that the readable version ?q=foo is also fine, and that this should be injected by extbase as well?
(I know that this breaks when multiple plugins on the same page use that parameter, but that's no problem here.)
(The parameter mapping seems already done when ActionController::processRequest() is called, so it must be done earlier.)
You could use the Extbase Plugin enhancer within the routing configuration.
See here: TYPO3 Advanced routing configuration Docs
TYPO3 would then transform the EXTbase URLs into an readable version.
Example:
without the routeEnhancer: yourdomain.com/?tx_example_search[q]=foo
with the routeEnhancer: yourdomain.com/foo
Tipp: You have to define all GET Params otherwise TYPO3 will show the cHash Param.
You can use the method \TYPO3\CMS\Core\Utility\GeneralUtility::_GP($var) in order to retrieve parameters from global variables GET/POST.
Or also \TYPO3\CMS\Core\Utility\GeneralUtility::_GET($var) or \TYPO3\CMS\Core\Utility\GeneralUtility::_POST($var).
Take care of security, those parameters are not sanitized !
If you really want to add the parameter to the action, you have to create an initializeAction() and set the parameter, something like this I guess :
public function initializeResultsAction() {
$myVar = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('q');
$this->request->setArgument('q', $myVar);
}

Can someone help me in Implementing XSSFilter

Can someone help me in Implementing XSSFilter, I need to check for XSS vulnerabilities in AEM code, I found that its method boolean check(ProtectionContext context, String src), checks for any XSS infected code, however what will be its context ? It would be nice if someone can share some example.
xssfilter=resourceResolver.adaptTo(XSSFilter.class);
String validjsonString = xssfilter.filter(jsonString);
LOGGER.debug("validjsonString:::::", validjsonString);
String[] uuidArray = getUUIDArray(validjsonString);
I am assuming that you are using the non-depracted Sling APIs here. In this case the ProtectionContext you are missing is coming from the following enum:
org.apache.sling.xss.ProtectionContext
The enum has two values:
HTML_HTML_CONTENT
Escape HTML for use inside element content (rules #6 and - to some degree - #1), using a policy to remove potentially malicous HTML
PLAIN_HTML_CONTENT
Escape plain text for use inside HTML content (rule #1)
Those rules mentioned in those definitions can be found here:
http://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet
So you could do either:
xssfilter.check(ProtectionContext.HTML_HTML_CONTENT, <your-string>);
xssfilter.check(ProtectionContext.PLAIN_HTML_CONTENT, <your-string>);
See: https://sling.apache.org/apidocs/sling11/org/apache/sling/xss/ProtectionContext.html#HTML_HTML_CONTENT

Fluid standalone view in BE context

Given you are in a BE or CLI context (e.g. sending emails via extbase command controller task), the following worked up to 7 LTS for rendering a fluid standalone view:
$view = $this->objectManager->get(StandaloneView::class);
$view->setTemplatePathAndFilename('/Absolute/Path/To/Template.html');
$view->setFormat('html');
$view->getRequest()->setControllerExtensionName('Myextensionname');
return trim($view->render());
However, in 8 LTS, this throws the following exception:
Tried resolving a template file for controller action "Standard->index" in format ".html", but none of the paths contained the expected template fileā€¦ No paths configured.
As suggested in the wiki page at https://wiki.typo3.org/How_to_use_the_Fluid_Standalone_view_to_render_template_based_emails#Usage_in_TYPO3_8.7, I tried setting layout and partial root paths for the view:
$view->setLayoutRootPaths(['EXT:Myextensionname/Resources/Private/Layouts/']);
$view->setPartialRootPaths(['EXT:Myextensionname/Resources/Private/Partials/']);
However, this won't do the trick.
Digging a bit deeper, I could imagine that one would have to set the controller and action name, e.g. by setting the controller context, but that does not seem to be a solid solution as multiple other class instances are tied to it.
What is the correct way to render fluid standalone views in 8 LTS?
Here an example from our current webproject where we want to show a simple note in backend context based on a FLUID HTML in TYPO3 8.7
protected function renderMarkup(): string
{
$standaloneView = GeneralUtility::makeInstance(StandaloneView::class);
$standaloneView->getRequest()->setControllerExtensionName('in2template');
$templatePathAndFile = 'EXT:in2template/Resources/Private/Templates/Tca/ToolbarNoteEmptyFields.html';
$standaloneView->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($templatePathAndFile));
$standaloneView->assign('toolbar', 'toolbarstuff');
return $standaloneView->render();
}
StandaloneView likes to receive all template paths (partial, template and layout root paths) so if you don't already provide all of them, you should do so. The reason being that the naming "Standalone" refers to the view being tied neither to a specific MVC action nor a specific extension context.
That said, if you use 8.7.5 there's a chance you are hit by a regression that is going to be solved by https://review.typo3.org/#/c/53917/ so it might be worth checking that out before you do a major refactoring. Technically the StandaloneView can be operated like a TemplateView with extension context, it's just not officially supported behavior and TYPO3 may not consistently apply all of the context you expect.
In my 8.7 extension I use the following code to get the StandaloneView:
$extbaseFrameworkConfiguration = $this->configurationManager->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
/** #var StandaloneView $emailView */
$emailView = $this->objectManager->get(StandaloneView::class);
$emailView->getRequest()->setControllerExtensionName($controllerExtensionName);
$emailView->getRequest()->setPluginName($pluginName);
$emailView->getRequest()->setControllerName($controllerName);
$emailView->setTemplateRootPaths($extbaseFrameworkConfiguration['view']['templateRootPaths']);
$emailView->setLayoutRootPaths($extbaseFrameworkConfiguration['view']['layoutRootPaths']);
$emailView->setPartialRootPaths($extbaseFrameworkConfiguration['view']['partialRootPaths']);
$emailView->setTemplate('Email/' . ucfirst($templateName));
$emailView->assignMultiple($variables);
$emailBody = $emailView->render();
In my function I gave the $controllerExtensionName, $pluginName and $controllerName as parameter with default values, so that other controllers/plugins can use this function, too.

TYPO3 new record appearing on wrong location in Backend List

I'm developing a new extension using ExtBase in TYPO3 (4.7) for a client.
I have however the strangest problem. In the back-end, my possible, new record types are - as usual - listed in the Insert new record Backend List. Usually each of these record-types are preceded by the module name (actually they are grouped right after the module name).. However, in my case, 1 or 2 of the record-types of any other extension appear within my extension's list as well.. I've been trying to figure out pretty much all that I can, I even copied the extension over to an entirely different TYPO3 installation, but the same problem persists..
If of any extension some records appear just below my extension's title, and I delete that particular extension, just some other record-types appear of another extension.
What's going on here??
Short & late answer:
i guess you have defined the title of your models in two different ways or with a non-existent languagefile in your ext_tables.php. Something like this:
Model1:
$TCA['tx_aaext_domain_model_one'] = array(
'ctrl' => array(
'title' => 'LLL:EXT:bn_news/Resources/Private/Language/locallang_db.xml:tx_bnnews_domain_model_categories',
Model2:
$TCA['tx_aaext_domain_model_two'] = array(
'ctrl' => array(
'title' => 'Static Title',
and/or your extension-name has an underscore like aa_extension, then this error can happen.
Make sure that both title-definitions are dynamic and begin with "LLL:EXT:" and point to an existing translation. Everything should be fine now.
Long answer will be to long :)