Set extbase Controller Action in plugin - typo3

I have set up an extbase extension in a TYPO3 4.5 site with the extension builder, containing just the default listAction in the controller.
Now I would like to add a new Action, and it doesn't work.
I don't need (aka. can't get to work) a flexform to choose the controller action.
As there's a field "Plugin mode", I thought I could just manually enter the action here:
And extend the plugin configuration as such in ext_localconf.php:
Tx_Extbase_Utility_Extension::configurePlugin(
$_EXTKEY,
'Pluginname',
array(
'Controllername' => 'list,listfeatured',
),
);
Also, in the controller, I have added a new action.
/**
* action listfeatured
*
* #return void
*/
public function listfeaturedAction() {
// do something
}
But, alas, the action is not called at all.
Did I interpret the field "plugin mode" wrong?
Did I miss something?
Alternatively: Can I set the action for a "backend" plugin via TS as well?

You need to use FlexForm correctly to set list of switchable actions.
Other option is creating another plugin for which default action is listfeatured.
If you will decide to use single plugin only just you need to show/describe us what did you try in FlexForm (probably new question)
Edit: As you showed us yourself in your question it's you deciding which Controller and action are default for given plugin, so to add new plugin which will use existing controller, just add this to your ext_localconf.php
Tx_Extbase_Utility_Extension::configurePlugin(
$_EXTKEY,
'MyFeaturedPlugin',
array(
'Controllername' => 'listfeatured',
),
);
you may also need to registerPlugin in your ext_tables.php if you want to be able to use it in BE (can be ommited if ie. plugin should be placed only with TS). You will do this with: Tx_Extbase_Utility_Plugin::registerPlugin

Besides FlexForm there is a further way of reading the field Plugin Mode in the plugin with PHP.
Right now, I'm working on a plugin and wish to distinguish between modi. Some modus B should be set from the very beginning of the request, even better it should not be sent over HTTP but read from the data model.
So I set the text 'myModusB` in the field "Plugin Mode", and in the plugin I inspect:
exit (print_r($this, true));
Then I find
[cObj] => TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer Object
...
[data] => Array
(
...
[select_key] => myModusB
...
So in the plugin by writing
$modus = $this->cObj->data["select_key"];
I'll get the text and can process it.
This is tested for version 6.1.3.

Related

Problem with setting a Plugin as a new CType

In order to have the full power of the TCA's showitem for configuring the back-end form for a plugin, I define it as a new CType, instead of a new list_type of the list CType.
I do this by registering it with addPlugin instead of the default method outlined in the official extension guide, using registerPlugin. In ext_tables.php:
TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPlugin(
[
// Label.
'LLL:EXT:my_ext/Resources/Private/Language/locallang.xlf:pi1.name',
// Plugin key.
'myext_pi1',
// Icon.
'pi1'],
'CType',
'my_ext'
);
Then I can just use, in Configuration/TCA/Overrides/tt_content.php:
$GLOBALS['TCA']['tt_content']['types']['myext_pi1'] = [
'showitem' => " ... "]
to configure it's back-end form display as I want.
But now, after successfully adding the plugin on a page from the back-end, when I try to view it from the front-end, I get the error:
ERROR: Content Element with uid "284" and type "myext_pi1" has no rendering definition!
It's not doing the usual: loading the controller action assigned to the plugin in ext_localconf.php with ExtensionUtility::configurePlugin (in ext_localconf.php).
Does anybody know what could I do to make it work?
The point in this case is, that the element does not just "act as if it were a custom content element", but it actually IS a custom content element.
So you will have to provide at least a basic configuration via
tt_content.myext_pi1
If you registered a plugin properly it might be enough to just copy the plugin configuration to the tt_content entry
tt_content.myext_pi1 < plugin.myext_pi1

TYPO3 set template view for controller action

I want to use the view template of the list action for my listByYear action. I tried setTemplatePathAndFilename without success. It still cannot find the template.
Sorry, the requested view was not found.
The technical reason is: No template was found. View could not be
resolved for action "listByYear" in class
"XXX\YYY\Controller\EventController".
/**
* action listByYear
* #param \XXX\YYY\Domain\Model\Event $event
*
* #return void
*/
public function listByYearAction(\XXX\YYY\Domain\Model\Event $event)
{
$date = $event->getStart();
$events = $this->eventRepository->findByYear($date->format('Y'));
$this->view->setTemplatePathAndFilename(
'typo3conf/ext/' .
$this->request->getControllerExtensionKey() .
'/Resources/Private/Templates/Event/List.html'
);
debug('typo3conf/ext/' .
$this->request->getControllerExtensionKey() .
'/Resources/Private/Templates/Event/List.html');
$this->view->assign('events', $events);
}
How do I make it use the template for the list?
The very short answer is, you can't. The view will already have been initialised and asked to resolve a template well before your action fires, indeed well before any point where you can affect the template filename that it would look for.
The template file that by convention would be resolved must always exist. This is what allows your controller action to render. You can then, but I would not recommend that you do, override the template file by setting the template name (the action).
Overall recommendation: use the default template naming logic. If you need to re-use templates, consider refactoring the template parts you need to reuse, placing them in partial templates.
// Do not forget the use in the header ...,
// or write fully qualified class path..
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Fluid\View\StandaloneView;
// then add something like this in your action before the assign...
// or maybe create a Standalone view: search the web for "Extbase Standaloneview"
// have a look at: /typo3/sysext/about/Classes/Controller/AboutController.php
$this->view = GeneralUtility::makeInstance(StandaloneView::class);
$this->view->setTemplate('ActionName');
$this->view->setTemplateRootPaths(['EXT:your_ext/Resources/Private/Templates']);
$this->view->setPartialRootPaths(['EXT:your_ext/Resources/Private/Partials']);
$this->view->setLayoutRootPaths(['EXT:your_ext/Resources/Private/Layouts']);
$this->view->assignMultiple([
'whatever' => $whatever,
'youLike' => $youLike,
]);

TYPO3 automatic page creation based on TCA record

I've special requirement on my project and I need help. I am using TYPO3 8.7.8. I've a custom extension to render tag labels in frontend. We can add the tags as TCA record in backend storage folder. In the TCA record, you can tag name. My requirement is, when I save the TCA record I want to create a TYPO3 page automatically with the same name as tag in a specific position. Everytime when I add a TCA record, I need to create corresponding page automatically. Is this possible? I can use hook while saving TCA. But is there any function to create pages automatically?
After automatic page creation, I want to insert a plugin content element in that page with a specific flexform value automatically. I know this is a strange requirement, but I would like to know if it is possible or not.
Exactly, you'd trigger a hook on saving and then as next step you can use the data handler to generate the new page (and possible content).
To create the page and content, use something like the following data structure
$data = [
'pages' => [
'NEW_1' => [
'pid' => 456,
'title' => 'Title for page 1',
],
],
'tt_content' => [
'NEW_123' => [
'pid' => 'NEW_1',
'header' => 'My content element',
],
],
];
Then call the datahandler with that structure:
$tce = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\DataHandling\\DataHandler');
$tce->stripslashes_values = 0;
$tce->start($data, []);
$tce->process_datamap();
Find out more in the docs at
https://docs.typo3.org/typo3cms/CoreApiReference/ApiOverview/Typo3CoreEngine/Database/Index.html#data-array
and
https://docs.typo3.org/typo3cms/CoreApiReference/ApiOverview/Typo3CoreEngine/UsingDataHandler/Index.html
Are you sure you need additional pages?
In general your problem sounds like you need one page where the plugin is inserted and where the plugin in dependency of an url-parameter (which can be converted with realurl into a path segment) shows only information depending of the selected record (tag).
If no tag is selected you can output a list with all available tags as a menu to navigate to all possible tags.
With a little effort (less than writing a hook like intended) you can add all tags to your menu.

Disable translation of Zend_Navigation elements

Is there any easy way to disable translation of some of the Zend Navigation elements?
e.g. in this case
$page = new Zend_Navigation_Page_Mvc(
array(
'label' => $blogPost->alreadyTranslatedTitleFromDb
// ...
)
);
$container->addPage($page);
Now, when I use:
$page->getLabel();
the label is translated twice. The same for breadcrumbs, sitemaps etc.
I wrote a patch with unit tests for this:
http://framework.zend.com/issues/browse/ZF-10948
If you want only some specific elements to be disabled, i think that only way is to use a partial view script and create your own logic for the menu.
You may add custom properties to the pages. Example: add a property doNotTranslate and in your view script check for this property to know if element should be translated or not.
More info about partial view script is available at http://framework.zend.com/manual/en/zend.view.helpers.html#zend.view.helpers.initial.navigation.menu

How can I check if Zend_Form_Elements has no decorators set

I find that even if I just declare an element like
$this->addElement('textarea', 'txt1');
I find that it already has decorators set
Zend_Debug::dump($this->getElement('txt1')->getDecorators());
http://pastebin.com/7Y24g62w
I want to test that I didn't set decorators using setDecorators() or using something like
$this->addElement('textarea', 'txt1', array(
'decorators' => array(...)
));
If I didn't set any decorators then apply default decorators, how can I do that. I want to apply default decorators per element basis, not using Zend_Form#setDisableLoadDefaultDecoraotrs()
There are two options, depending on how exactly you want to be sure a decorator hasn't been changed.
Decorator without option
If you just want to know if all default decorators are set, without thinking about the options of each decorator, you can use this option. Of course you can alter options of a default decorator and this method won't recognize this (but it is faster than an extensive check). Unfortunately the default decorators are hard-coded in the Zend_Form_Element at Zend_Form_Element::loadDefaultDecorators() so you need to copy that list. When in future releases the chain changes, you need to alter your code.
<?php
$default = array(
'Zend_Form_Decorator_ViewHelper',
'Zend_Form_Decorator_Errors',
'Zend_Form_Decorator_Description',
'Zend_Form_Decorator_HtmlTag',
'Zend_Form_Decorator_Label',
);
$decorators = array_keys($element->getDecorators());
if ($decorators === $default) {
// They are the same
}
Check decorators with all options
Here you create a copy of your element and at this copy you reload all default decorators. They get instantiated again so it takes a bit more resources, but all options of the decorators are checked as well.
$clone = clone $element;
$clone->clearDecorators()
->setDisableLoadDefaultDecorators(false)
->loadDefaultDecorators();
if ($clone === $element) {
// They are the same
}