Passing arguments to a different controller or alternatives - typo3

Inside my extbase extension I have an appointment model and users can write feedback to how the appointment was.
So I created a feedback model with different fields.
Now what should I implement for when the user clicks on the "Create Feedback" button?
So far I got this, but it's not working:
<f:link.action action="edit" controller="Feedback" arguments="{appointment:appointment}">
I get the the error:
Argument 1 passed to
...Controller\FeedbackController::newAction() must be an instance of
...\Model\Appointment, none given
FeedbackController:
/**
* action new
* #param ...\Domain\Model\Appointment $appointment
* #return void
*/
public function newAction(...\Domain\Model\Appointment $appointment) {
$this->view->assign('appointment', $appointment);
}
Why do I get this error? (the appointment object was definitely there, I debugged it)
I figure it must've something to do with the switch from AppointmentController to FeedbackController.
What's the best way to implement this?

You need the pluginName parameter in your link generation if you use different plugins.
<f:link.action action="edit" controller="Feedback" pluginName="your_plugin" arguments="{appointment:appointment}">
When generating a link TYPO3 prepends the "namespace" of the argument to the link like this: tx_myplugin[action]=new. Make sure, that the pluginName is the same one you defined in ext_localconf.php. In this case the pluginName would be your_plugin.
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
'Vendor.' . $_EXTKEY,
'your_plugin',
array(
'Feedback' => 'new',
),
// non-cacheable actions
array(
'Feedback' => '',
)
);

Check the plugin-controller-action array in your ext_localconf.php and post it. Maybe there is something wrong.

If you get this error :
Argument 1 passed to ...Controller\FeedbackController::newAction()
must be an instance of ...\Model\Appointment, none given
it's because you give the controler a NULL object and taht's not allowed with your controller.
To avoid this error, you could allow NULL object in your controller :
/**
* action new
* #param ...\Domain\Model\Appointment $appointment
* #return void
*/
public function newAction(...\Domain\Model\Appointment $appointment=NULL) {
$this->view->assign('appointment', $appointment);
}
this is weird because in your link, you call an action 'edit' and you have an error in 'newAction' controller instead of 'editAction' controller, you should have the 'edit' action allowed for your plugin (cachable or not) :
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
'Vendor.' . $_EXTKEY,
'your_plugin',
array(
'Feedback' => 'edit',
),
// non-cacheable actions
array(
'Feedback' => 'edit',
)
);
and as Natalia wrote add the plugin name if the action you want to call belongs to another plugin.
<f:link.action action="edit" controller="Feedback" pluginName="your_plugin" arguments="{appointment:appointment}">
Florian

Related

TYPO3 extbase, the php based views do not work when migrating from 9 to 10 version

I have developed a custom TYPO3 extbase extension that was perfectly worked on 8 and 9 version of TYPO3.
Recently I upgraded my installation to TYPO3 10 version but the php based views of my TYPO3 extbase extension do not work anymore.
The error that is displayed is:
Sorry, the requested view was not found.
The technical reason is: No template was found. View could not be resolved for action "getIcal" in class "Luc\Lucevents2\Controller\EventController"
I have read the instructions in the page
https://docs.typo3.org/m/typo3/book-extbasefluid/10.4/en-us/8-Fluid/9-using-php-based-views.html, but there is nothing different from what I have already done in my extension.
So, I am very confused because there is no explanation why the code stopped to work, the above link doesn't include any instructions about deprecated code or possible changes after migration!!
Could you give me any help?
Thank you very much!
George
I hit this problem today. The documentation for "php based views" seems to be outdated.Below is a description of my setup and the solution for TYPO3 10
What I had:
My situation was that I had a Controller with a showAction() action method.
In typoscript, I had setup a new format through the type parameter. Something like
rss = PAGE
rss {
typeNum = 58978
10 =< tt_content.list.20.skevents_eventfeeds
}
For this type (parameter type=58978) I had setup a class named View\EventFeeds\ShowRss with a render() method.
TYPO3 automatically resolved this class based on the type (rss) and the action name (show). This does not work any more.
What solves this issue:
in order for TYPO3 to find the correct class with the render method, it is sufficient to set the defaultViewObjectName variable of the Controller to the correct class name for the specific action. This can be done in the controller with the following new method
public function initializeShowAction()
{
$this->defaultViewObjectName = \Skar\Skevents\View\EventFeeds\ShowRss::class;
}
So now, before calling the showAction method, defaultViewObjectName is set to my ShowRss class which produces the output.
Please note that my ShowRss class extends \TYPO3\CMS\Extbase\Mvc\View\AbstractView . According to https://docs.typo3.org/m/typo3/book-extbasefluid/master/en-us/8-Fluid/9-using-php-based-views.html this is deprecated in TYPO3 11 and will have to change for TYPO3 12
the static template is already included and all the other operations of the extension are working very well except the php based views. The ext_localconf.php looks as follows: <?php
defined('TYPO3_MODE') || die('Access denied.');
$boot = function () {
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
'Luc.Lucevents2',
'Luceventsdisplay',
[
'Event' => 'list, show, delete, edit, monthview, test, ajax, deleteConfirm, showRss, getIcal, addForm, add, editForm, importeventtoforum',
'Channel' => 'list, show',
'Tag' => 'filter, show'
],
// non-cacheable actions
[
'Event' => 'list, show, delete, edit, monthview, test, ajax, deleteConfirm, showRss, getIcal, addForm, add, editForm, importeventtoforum',
'Channel' => 'list, show',
'Tag' => 'filter, show'
]
);
};
$boot();
unset($boot);
The action is registered in EventController.php and looks as follows:
/**
* action geticalaction
*
* #param \Luc\Lucevents2\Domain\Model\Event $event
* #return void
*/
public function getIcalAction(\Luc\Lucevents2\Domain\Model\Event $event = NULL)
{
$base_url = $this->request->getBaseUri();
$channel=$this->settings['channel_for_simple_users'];
if($this->request->hasArgument('duration'))
{
if ($this->request->getArgument('duration')=='6month') {
$duration=$this->request->getArgument('duration');
}
else
{
$duration='month';
}
$events = $this->eventRepository->get_events_for_rss_and_ical($duration,$channel);
$eventsarray= array();
foreach ($events as $obj){
$this->uriBuilder->setCreateAbsoluteUri(true);
$uri = $this->controllerContext->getUriBuilder()
->setUseCacheHash(false)
->uriFor('show', array("event" => $obj->getUid()));
$eventsarray[] = array($obj->getTitle(), $obj->getDescription(), $obj->getStartdatetime(),$obj->getEnddatetime(), $obj->getBuildingid(), $obj->getRoomid(), $obj->getPlace(), $obj->getCrdate(), $uri, $obj->getUid());
}
$this->view->assign('events', $eventsarray);
$this->view->assign('baseurl', $base_url);
}
else
{
$this->uriBuilder->setCreateAbsoluteUri(true);
$uri = $this->controllerContext->getUriBuilder()
->setUseCacheHash(false)
->uriFor('show', array("event" => $event->getUid()));
$this->view->assign('event', $event);
$this->view->assign('baseurl', $base_url);
$this->view->assign('uri', $uri);
}
}
Thank you very much!

plugin.xx.view.pluginNamespace = Controller are not allowed by this Plugin

I have started a extension under TYPO3 6.2, and migrated this to TYPO3 7. Now it seems, that all links to Controller/Action combinations are broken.
In my TypoScript I have set:
plugin.tx_extensionname.view.pluginNamespace = tx_extensioname
In ext_tables.php I have set:
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin(
$_EXTKEY,
'Pi1',
'Controller1: DoSomeLogic1'
);
....
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin(
$_EXTKEY,
'Pi12',
'Controller12: DoSomeLogic12'
);
In ext_localconf.php the plugins get configured:
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
'MRU.' . $_EXTKEY,
'Pi2',
array(
'Basket' => 'list, add, remove, address, setDeliveryCountryJson',
'Order' => 'directorder, savedirectorder, accountorder, loginorder, saveloginorder, saveaccountorder, overview, doOrder, paymentSuccess, paymentFailure, paymentNotification, paymentCancel',
'Payment' => 'index'
),
// non-cacheable actions
array(
'Basket' => 'list, add, remove, address, setDeliveryCountryJson',
'Order' => 'directorder, savedirectorder, accountorder, loginorder, saveloginorder, saveaccountorder, overview, doOrder, paymentSuccess, paymentFailure, paymentNotification, paymentCancel',
'Payment' => 'index'
)
);
On a page (id 42) I have placed the plugin Pi2. The Basket Controller is shown with list action. All fine. The URL is like this:
http://www.example.com/index.php?id=42
If I add the namespaced Controller Parameter, like this
http://www.example.com/index.php?id=42&tx_extensionname[controller]=Basket
I get instantly the
#1313855173: The controller "Basket" is not allowed by this plugin. Please check for TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin() in your ext_localconf.php.
Exception. If I add the pluginname to the URI like this
http://www.example.com/index.php?id=42&tx_extensionname_pi2[controller]=Basket
no expecption is thrown. But if I call a action like this
http://www.example.com/index.php?id=42&tx_extensionname_pi2[controller]=Basket&tx_extensionname_pi2[action]=add
this action gets never called. The Controller with it's first action is called.
I did the update some weeks ago, it is only a dev system, but today I cleared all caches and the error occours. Have I missed something with plugin combined namespaces and the registration/configuration/linking of it?
Ok, it seems that this resolve my issue:
plugin.tx_extensionname.mvc.callDefaultActionIfActionCantBeResolved = 1
With callDefaultActionIfActionCantBeResolved = 0 or missing the above, i get the Not Allowed Exception. Settings this to 1 the Controller and Action gets called.

Zf2 multicheckbox at least one element is always required

I can't validate a zf2 form with multicheckbox because at least one checkbox is always required.
I found a lot of reference to this issue (for example here - https://github.com/zendframework/zf2/issues/4845), but i didn't found a solution for this.
Does anybody know how to solve this problem ?
UPDATE: I use a doctrine 2 objectmulticheckbox which is extended from zf2 multichechbox. As is commented below the override of getInputFilterSpecification method, will solve the problem with form validation, but the values will still remain in database (values populated by objectmulticheckbox).
I found a seemingly easier way to get around this issue by setting the input filter 'required' to false inside the controller, after the form is instantiated.
<?php
$form = new CampaignForm($multiCheckboxOptions); // Setting up checkbox in form class
$form->getInputFilter()->get('my_multi_checkbox')->setRequired(false);
?>
You can override the getInputFilterSpecification function on your form to set the field to not be required. For example:
public function getInputFilterSpecification() {
return array(
[...]
'the-multi-checkbox-field' => array(
'required' => false,
),
[...]
);
}
Ok i did a little hack to solve this problem.
So I added this code in the action controller:
$form->bind($client);
/** #var $request Request */
$request = $this->getRequest();
if ($request->isPost()) {
$form->setData($request->getPost());
if ($form->isValid()) {
/** #var $client Client */
$client = $form->getData();
// hack because of - https://github.com/zendframework/zf2/issues/4694
if($request->getPost('reportSettings') === null){
$client->setReportSettings(null); // set null to remove all associations with this client
}
And also as it is described in the first answere, in form should be rewritten getInputFilterSpecification method, for field that shouldn't be required.

Zend_Navigation_Page and onclick attribute?

I've been asked to add some Google event tracking to a link on a site I'm 'fixing'.
This relies on the 'onclick' attribute and the ZEND framework (1.11.11) application seems to generate those links as described below.
I can't find out how to add custom attributes to this function, specifically, 'onclick'.
Is this even possible? I've never got along with Zend and any gurus out there will probably know far better than I if it's even possible.
/**
* #return Zend_Navigation_Page_Uri
*/
public function getBrochurePageUri()
{
return new Zend_Navigation_Page_Uri(array(
'label' => 'Brochure request',
'uri' => 'http://www.website.com/brochure/'
)
);
}
try adding the following:
'attribs' => array('onclick'=>'somefunction(params)')
resulting in the following:
return new Zend_Navigation_Page_Uri(array(
'label' => 'Brochure request',
'uri' => 'http://www.website.com/brochure/',
'attribs' => array('onclick'=>'somefunction(params)')
)
);

Zend adding parameter to URL before generating view

The title might be misleading but I'm trying to do something very simple but cant figure it out.
Lets say I have a Question controller and show action and question id is the primary key with which I look up question details - so the URL looks like this
http://www.example.com/question/show/question_id/101
This works fine - So when the view is generated - the URL appears as shown above.
Now in the show action, what I want to do is, append the question title (which i get from database) to the URL - so when the view is generated - the URL shows up as
http://www.example.com/question/show/question_id/101/how-to-make-muffins
Its like on Stack overflow - if you take any question page - say
http://stackoverflow.com/questions/5451200/
and hit enter
The question title gets appended to the url as
http://stackoverflow.com/questions/5451200/make-seo-sensitive-url-avoid-id-zend-framework
Thanks a lot
You will have to add a custom route to your router, unless you can live with an url like:
www.example.com/question/show/question_id/101/{paramName}/how-to-make-muffins
You also, if you want to ensure that this parameter is always showing up, need to check if the parameter is set in the controller and issue a redirect if it is missing.
So, in your bootstrap file:
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
public function _initRoutes ()
{
// Ensure that the FrontController has been bootstrapped:
$this->bootstrap('FrontController');
$fc = $this->getResource('FrontController');
/* #var $router Zend_Controller_Router_Rewrite */
$router = $fc->getRouter();
$router->addRoutes( array (
'question' => new Zend_Controller_Router_Route (
/* :controller and :action are special parameters, and corresponds to
* the controller and action that will be executed.
* We also say that we should have two additional parameters:
* :question_id and :title. Finally, we say that anything else in
* the url should be mapped by the standard {name}/{value}
*/
':controller/:action/:question_id/:title/*',
// This argument provides the default values for the route. We want
// to allow empty titles, so we set the default value to an empty
// string
array (
'controller' => 'question',
'action' => 'show',
'title' => ''
),
// This arguments contains the contraints for the route parameters.
// In this case, we say that question_id must consist of 1 or more
// digits and nothing else.
array (
'question_id' => '\d+'
)
)
));
}
}
Now that you have this route, you can use it in your views like so:
<?php echo $this->url(
array(
'question_id' => $this->question['id'],
'title' => $this->question['title']
),
'question'
);
// Will output something like: /question/show/123/my-question-title
?>
In your controller, you need to ensure that the title-parameter is set, or redirect to itself with the title set if not:
public function showAction ()
{
$question = $this->getQuestion($this->_getParam('question_id'));
if(!$this->_getParam('title', false)) {
$this->_helper->Redirector
->setCode(301) // Tell the client that this resource is permanently
// residing under the full URL
->gotoRouteAndExit(
array(
'question_id' => $question['id'],
'title' => $question['title']
)
);
}
[... Rest of your code ...]
}
This is done using a 301 redirect.
Fetch the question, filter out and/or replace URL-illegal characters, then construct the new URL. Pass it to the Redirector helper (in your controller: $this->_redirect($newURL);)