Writing a class for the Joomla “Result” event

This is a continuation of the article “Every Joomla event has its own class.” In it I will tell you how to create an event class that should return some result.

Why did I need such an event?

To calculate the cost and arrange delivery to SDEK, you need to calculate the size and weight of the parcels. On different sites, this calculation occurs differently: it can be one box for all products in the order, or each product in its own box, or, for example, chairs that are stacked several times in one box.

I decided to move the calculation of parcel space sizes into separate plugins and use the required plugin on each site.

Now let’s figure out how to create a class for this event in Joomla 4. Looking ahead, I’ll say that the interface and traits will help us with this.

Event name: onRadicalMartCdekCalculatorGetPackages .

Event class: GetPackagesEvent.

Parent class: Joomla\CMS\Event\AbstractEvent .

Interface

Joomla\CMS\Event\Result\ResultAwareInterface

Used for events whose handlers must return something when called, similar to how many plugin events worked in earlier versions of Joomla.

This interface is partially implemented by the trait ResultAware. Method typeCheckResult
implemented by various traits ResultTypeAware. Your event should be used as a trait ResultAwareand one of the traits ResultTypeAware. For example, if the event returns objects, you need to use traits ResultAware And ResultTypeObjectAware in your class.

Joomla offers the following ready-made “ResultTypeAware” traits:

  • ResultTypeArrayAware;

  • ResultTypeBooleanAware;

  • ResultTypeFloatAware;

  • ResultTypeIntegerAware;

  • ResultTypeMixedAware;

  • ResultTypeNumericAware;

  • ResultTypeObjectAware;

  • ResultTypeStringAware.

Traits implement simple checking of added results by functions is_array, is_boolean and others, as you might guess from their names.

Only slightly different ResultTypeMixedAware which doesn't check anything and ResultTypeObjectAwarewhich we will consider in more detail later.

Traits

Joomla\CMS\Event\Result\ResultAware

Properties:

<?php
bool $preventSetArgumentResult = false;

Prevents setting the result argument directly using setArgument('result', $value) instead of using addResult($value).

Methods:

<?php
public function addResult($data): void

Adds data to the event results array.

<?php
protected function onSetResult(array $value)

Argument setter 'result'when set to true event class property $preventSetArgumentResultthrows an exception.

Thus the trait ResultAware does not allow you to overwrite the results of other plugins. Plugins can only add their results to an array.

Joomla\CMS\Event\Result\ResultTypeObjectAware

This trait implements ResultAwareInterface::typeCheckResult($data) to check the type of the added result.

Events using this trait (and the trait ResultAware)will expect event handlers to set the results of the corresponding class.

If you do not specify a list of valid result classes, any PHP object will match this type check.

Properties:

<?php
protected $resultIsNullable = false;

Can result attribute values ​​also be NULL?

<?php
protected $resultAcceptableClasses = [];

Valid class names for result values.

Methods:

<?php
public function typeCheckResult($data): void

Checks the type of data added to the result argument and throws an exception if there is a mismatch.

This is the event class I got:

<?php
/**
 * @copyright   (c) 2013-2024 Nekrasov Vitaliy <nekrasov_vitaliy@list.ru>
 * @license     GNU General Public License version 2 or later;
 */
namespace Joomla\Component\Radicalmartcdek\Administrator\Event\Service\CalculatorDelegate;

use Joomla\CMS\Event\AbstractEvent;
use Joomla\CMS\Event\Result\ResultAware;
use Joomla\CMS\Event\Result\ResultAwareInterface;
use Joomla\CMS\Event\Result\ResultTypeObjectAware;
use Joomla\Component\Cdek\Site\Interface\CalculatorDelegateInterface;
use CdekSDK2\Model\Request\Calculator\TariffListPost\PackageRequest;
use function defined;

// phpcs:disable PSR1.Files.SideEffects
defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects

/**
 * @since 1.0.0
 */
class GetPackagesEvent extends AbstractEvent implements ResultAwareInterface
{
	use ResultAware;
	use ResultTypeObjectAware;

	/**
	 * @param   string  $eventName  Event name
	 * @param   array   $arguments  Arguments
	 *
	 * @since 1.0.0
	 */
	public function __construct(string $eventName, array $arguments)
	{
		parent::__construct($eventName, $arguments);

		$this->preventSetArgumentResult = true; // запрещаем прямую установку агрумента 'result'
		$this->resultAcceptableClasses = [PackageRequest::class]; // класс для работы с посылкоместами Сдэка
	}

	/**
	 * @param   CalculatorDelegateInterface  $value  Subject
	 *
	 * @return CalculatorDelegateInterface
	 *
	 * @since version
	 */
	protected function onSetSubject(CalculatorDelegateInterface $value): CalculatorDelegateInterface
	{
		return $value;
	}

	/**
	 * @param   CalculatorDelegateInterface  $value  Subject
	 *
	 * @return CalculatorDelegateInterface
	 *
	 * @since version
	 */
	protected function onGetSubject(CalculatorDelegateInterface $value): CalculatorDelegateInterface
	{
		return $value;
	}

	/**
	 * @return CalculatorDelegateInterface
	 *
	 * @since 1.0.0
	 */
	public function getSubject(): CalculatorDelegateInterface
	{
		return $this->getArgument('subject');
	}

	/**
	 * @return PackageRequest[]
	 *
	 * @since 1.0.0
	 */
	public function getResult(): array
	{
		return $this->arguments['result'];
	}
}

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *