Пишем класс для «Result»-события Joomla

от автора

Это продолжение статьи «Каждому событию Joomla — свой класс». В нём я расскажу как создать класс события, которое должно возвращать какой-либо результат.

Для чего мне потребовалось такое событие?

Для рассчёта стоимости и оформления доставки в Сдэк надо рассчитать размеры и вес посылок. На разных сайтах этот рассчёт происходит по разному: это может быть одна коробка для всех товаров в заказе, или каждый товар в своей коробке, или, например, стулья, которые штабелируются по нескольку штук в одну коробку.

Я решил вынести рассчёт размеров посылкомест в отдельные плагины и на каждом сайте использовать нужный плагин.

Теперь разберёмся как создать класс для этого события в Joomla 4. Забегая наперёд, скажу что нам в этом помогут интерфейс и трейты.

Имя события: onRadicalMartCdekCalculatorGetPackages .

Класс события: GetPackagesEvent.

Родительский класс: Joomla\CMS\Event\AbstractEvent .

Интейфейс

Joomla\CMS\Event\Result\ResultAwareInterface

Используется для событий, обработчики которых должны возвращать что-то при вызове, аналогично тому, как работали многие события плагинов в более ранних версиях Joomla.

Этот интерфейс частично реализован трейтом ResultAware. Метод typeCheckResult
реализован различными трейтами ResultTypeAware. Ваше событие должно использовать как трейт ResultAware, так и один из трейтов ResultTypeAware. Например, если событие возвращает объекты, вам необходимо использовать трейты ResultAware и ResultTypeObjectAware в вашем классе.

Joomla предлагает следующие готовые «ResultTypeAware» трейты:

  • ResultTypeArrayAware;

  • ResultTypeBooleanAware;

  • ResultTypeFloatAware;

  • ResultTypeIntegerAware;

  • ResultTypeMixedAware;

  • ResultTypeNumericAware;

  • ResultTypeObjectAware;

  • ResultTypeStringAware.

Трейты реализуют простую проверку добавляемых результатов функциями is_array, is_boolean и др. как можно догадаться из их названий.

Немного отличаются только ResultTypeMixedAware , который ничего не проверяет и ResultTypeObjectAware, который мы далее рассмотрим подробнее.

Трейты

Joomla\CMS\Event\Result\ResultAware 

Свойства:

<?php bool $preventSetArgumentResult = false;

Запрещает установку аргумента результата напрямую с помощью setArgument('result', $value) вместо использования addResult($value).

Методы:

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

Добавляет данные в массив результатов события.

<?php protected function onSetResult(array $value)

Сеттер аргумента 'result', при установленном в true свойстве класса события $preventSetArgumentResult, бросает исключение.

Таким образом трейт ResultAware не позволяет перезаписать результаты работы других плагинов. Плагины могут только добавлять свои результаты в массив.

Joomla\CMS\Event\Result\ResultTypeObjectAware

Этот трейт реализует ResultAwareInterface::typeCheckResult($data) для проверки типа добавлемого результата.

События, использующие этот трейт (и трейт ResultAware), будут ожидать, что обработчики событий установят результаты соответствующего класса.

Если вы не зададите список допустимых классов результатов, любой объект PHP будет соответствовать этой проверке типа.

Свойства:

<?php protected $resultIsNullable = false;

Могут ли значения атрибутов результата также быть NULL?

<?php protected $resultAcceptableClasses = [];

Допустимые имена классов для значений результатов.

Методы:

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

Проверяет тип данных, добавляемых к аргументу результата и бросает исключение в случае несоответствия.

Вот такой у меня получился класс события:

<?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']; } } 


ссылка на оригинал статьи https://habr.com/ru/articles/853820/