Это продолжение статьи «Каждому событию 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/
Добавить комментарий