?
avatar zero-24
zero-24
15 Aug 2017

Steps to reproduce the issue

https://github.com/joomla/joomla-cms/blob/4.0-dev/libraries/src/CMS/Application/EventAware.php#L111-L114

Expected result

Somhow the result is passed to the event.

Actual result

$result = $dispatcher->dispatch($eventName, $event);

=> returns a Joomla/Event/Event object that does not contain the result

return !isset($result['result']) || is_null($result['result']) ? [] : $result['result'];

This checks for an array and as $result is never an array it returns an empty array.

System information (as much as possible)

I don't know what was the idea behind that?

Here is the debug output:
image

I don't know who wrote that code mybe @wilsonge or @mbabker can help here and understand what is going on?

Additional comments

cc @kasvith

avatar zero-24 zero-24 - open - 15 Aug 2017
avatar joomla-cms-bot joomla-cms-bot - labeled - 15 Aug 2017
avatar joomla-cms-bot joomla-cms-bot - change - 15 Aug 2017
Labels Added: ?
avatar kasvith
kasvith - comment - 15 Aug 2017

@zero-24 for events that accept no arguments it works, it call registerLegacyEvent() and it does really return after method calling

avatar mbabker
mbabker - comment - 15 Aug 2017

The base AbstractEvent class implements PHP's ArrayAccess interface so the event arguments are accessible when referencing the object as an array. $event->getArgument('result') is the same as $event['result'].

avatar zero-24
zero-24 - comment - 15 Aug 2017

this means a plugin needs to return $event->result = $result ? and no longer return $result?

avatar kasvith
kasvith - comment - 15 Aug 2017

I tried
$event->result = "some result"; return $event;

Still the problem remains. $results is an empty array

avatar zero-24
zero-24 - comment - 15 Aug 2017

sure. the $event->result = "some result" i have added to the plugin is just the reason we have a result key in the array output in the debugger. So even with $event->getArgument('result') it would return nothing as it is noting to be added by a simple return $value;

avatar mbabker
mbabker - comment - 15 Aug 2017

$event->result is not the same as $event['result']

For all 3.x style code, working without the new Event objects, what they are doing now works just fine.

If you dispatch an event through the application triggerEvent method, as all of core does, and your plugin does not use the legacy behavior (meaning a method has one argument, a typehinted Event object), the method must set data explicitly to the result argument. See the quickicon plugin I updated.

In short, the new convention is an event listener does not return a value on its own, it must add data to the Event object.

avatar kasvith
kasvith - comment - 15 Aug 2017

Thanks @mbabker

avatar kasvith
kasvith - comment - 15 Aug 2017

For anyone who is facing issue getting result from
$results = \JFactory::getApplication()->triggerEvent('onSomeEvent', $event);
If you gets an empty array every time do as follow.

In your plugin's onSomeEvent($event) do not return your result.

Instead please do following

In plugin

public function onSomeEvent($event)
{
     // your code

	$result = 'your result';
	$event->setArguments('result', $result);
} 

This will return what you set in $result to the $results as an array.
Do not use legacy return with J4.x

avatar zero-24 zero-24 - change - 15 Aug 2017
Status New Closed
Closed_Date 0000-00-00 00:00:00 2017-08-15 13:57:43
Closed_By zero-24
avatar zero-24 zero-24 - close - 15 Aug 2017
avatar mbabker
mbabker - comment - 15 Aug 2017

Just to clarify this a bit more, and demonstrating with practical examples in case others stumble upon this later.

In 4.x, if using 3.x and earlier style plugin conventions, a regular return is OK (as was previously the case), see https://github.com/joomla/joomla-cms/blob/f7c3f3abfbd4527bbd81d46744eea005982d8de9/plugins/quickicon/extensionupdate/extensionupdate.php

In 4.x, if using the new 4.x conventions, a return value is not used at all and you must set any return value (if applicable) to the Event object's result argument, see https://github.com/joomla/joomla-cms/blob/f7c3f3abfbd4527bbd81d46744eea005982d8de9/plugins/quickicon/joomlaupdate/joomlaupdate.php

Also, best practice as it relates to the result argument is this (to prevent overwriting previously set values):

$result = $event->getArgument('result', []); // Or $result = $event['result'] ?? [];
$result[] = 'Added result data';
$event->setArgument('result', $result); // Or $event['result'] = $result;
avatar kasvith
kasvith - comment - 15 Aug 2017

I will add this to gist i created
Thank you @mbabker

avatar mbabker
mbabker - comment - 15 Aug 2017

Your gist is still missing one important note.

For the "This will return what you set in $result to the $results as an array." statement to be true, your event listener MUST typehint the argument as a Joomla\Event\EventInterface implementation. As in you must explicitly write code using the new conventions. As is, your gist would actually use the legacy method because the parameter is not typehinted as an event object.

The existing 3.x conventions are still used by default and will continue to work until 5.0.

The reason I emphasize this is because they are two different approaches and must be treated differently, "Do not use legacy return with J4.x" only applies under a very explicit circumstance and I just want to make sure somebody doesn't come across things later and think we made a major B/C break with plugins.

avatar kasvith
kasvith - comment - 15 Aug 2017

can you check again

avatar mbabker
mbabker - comment - 15 Aug 2017

Looks good, thanks.

avatar kasvith
kasvith - comment - 15 Aug 2017

you are welcome

Add a Comment

Login with GitHub to post a comment