Новый класс waEvent

Пришло время обновиться нашему обработчику ивентов.

Раньше вся логика жила в waSystem, что мешало, как тестированию так и масштабированию методу обработки ивентов. Чтобы решить эту проблему был создан новый класс - waEvent. Так же в новый класс добавлен новый функционал по подписке на ивенты.

Начнем с простого. Сигнатура добавления хуков не изменилась. Если хотите добавить хук в собственное приложение, то используйте старый вызов.

Добавление хука в приложение: 

wa('id_приложения')->event('имя_ивента', 'передаваемая_информация', 'ключи_для_плагинов');
//или
wa()->event(array('id_приложения', 'имя_ивента'), 'передаваемая_информация', 'ключи_для_плагинов');

//Пример 
wa('shop')->event('frontend_products', $event_params);

Старые методы подписок на хуки не изменились. 

Классические способы:

В приложениях:

Требуется создать файл c обработчиком. Он должен быть расположен в папке wa-apps/app_id/lib/handlers.

Сигнатура названия файла:

id_приложения.имя_ивента.hanlder.php
id_приложения.имя_ивента.имя_маски.hanlder.php

//Пример

wa-apps/app_id/lib/handlers/shop.start_followup_cli.handler.php  
wa-apps/app_id/lib/handlers/shop.order_action.pay.handler.php

Готовый класс: 

<?php

class app_IdEvent_app_idEvent_nameHandler extends waEventHandler
{
    public function execute(&$params, $event_name = null)
    {
        $result = null;
        //Логика кода;
        return $result;
    }
}

Для хандлеров приложений стандартный метод execute. 


$event_name теперь всегда передается в методы для обработки. Раньше это было опционально для плагинов. Если ваш обработчик наследуется от waEventHandler то сигнатура метода execute будет 

public function execute(&$params, $event_name = null)

или

public function execute(&$params)

В плагинах:

В plugin.php добавляете ключ handler. Далее в него добавляете ивенты на которые хотите подписаться и методы, которые требуется вызвать для этих ивентов. Методы вызываются из главного класса вашего плагина. Они должны быть публичными и не статичными.

Пример:

return array(
    'name'     => 'debug',
    '...',
    'handlers' => array(
        'event_name'  => 'methodName',
        'event_name2' => array('methodName', 'methodName2',),
    )
);

Дополнительно: 

Обратите внимание, на то, что от одного плагина или приложения может быть только один ответ. Т.е. если методов много, то они будут вызываться по очереди до первого метода у которого результат не будет равен NULL. После вызов методов прекращается.

Нововведения 

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

Термины

Wildcard приложение - это не обозначенное приложение. На случай если вам нужно проигнорировать приложение и подписаться только на ивент. Помечается *.

Wildcard ивент - это ивенты, имя которых состоит из масок или регулярных выражений. 

Точный ивент - это имя ивента из обработчика, которое должно полностью соответствовать имени ивента из хука. 

Точное приложение - это id приложения, для которого надо вызвать обработчики.

Звездочка придумана для того, чтобы там хранить все обработчики с необычными именами ивентов (регулярки, маски). Они будут вызываться всегда. Поэтому старайтесь пользоваться регулярными выражениями или масками в редких случаях. И только при крайней необходимости используйте wildcard приложение.

Новый вид подписок на ивенты

В приложениях и плагинах это делается в разных местах (которые описаны ниже), но формат добавления будет везде одинаковый.

Вот самый расширенный вариант массива 

array(
    'event_app_id' => 'ID приложения', //не обязательно
    'file'         => 'имя файла', //не обязательно. Недоступен плагинам
    'event'        => 'имя ивента',  //Обязательно
    'class'        => 'название класса', //Обязательно
    'method'       => 'название метода' || array('название метода 1', 'название метода 2'),//Обязательно
),

Расшифровка:

event_app_id - ID приложения для которого вызывается ивент. По умолчанию будет браться wildcard приложение.

Пример: 

'event_app_id' => '*' || 'event_app_id' => 'shop' || 'event_app_id' => 'crm'

file - имя файла в папке handlers конкретного приложения. Это ключ доступен только приложениям. Существует на случай если файл не попал в автолоад (для плагинов используйте классические классы)

Пример для приложения: 

'file' => wa-apps/shop/lib/handlers/shop.order_action.pay.handler.php

event - это имя вызываемого ивента. Тут может быть точное соответствие, маска или регулярное выражение.

Точное соответствие:  'order_action.pay'. Экранируется

Маска - 'order_action.*' . Экранирует частично. Все символы кроме последних .* будут экранированы. Результат будет 'order_action\..*'

Регулярное выражение - '/.*/'. Не экранируется по умолчанию. Важно, чтобы регулярные выражения начинались с / или ~ иначе имя ивента будет считаться точным соответствием.

//Точное соответствие
'event' => 'event_name',
//Маска
'event' => 'event_name.*'
//Регулярное выражение
'event' => '/\w*/' 

class - Название класса в котором находятся обработчики. Будет использован для создания объекта.

method - Может быть как строкой, так и массивом методов. Методы должны быть публичными и не статическими. 

Подписка в приложениях:

В папке wa-apps/app_id/lib/handlers Требуется создать файл wildcard.php. Он должен возвращать многомерный массив, в котором находятся данные обработчиков.

Пример

return array(
    array(
        'event'        => 'event_name',
        'class'        => 'app_idEvent_app_idEventNameHandler',
        'method'       => array('execute', 'extraMethod'),
        'event_app_id' => 'event_app_id',
        'file'         => 'wa-apps/app_id/lib/handlers/event_app_id.custom_event.handler.php',
    )
);

Рекомендация: Не ссылайтесь на классы, предназначение которых не обработка ивентов. Старайтесь не создавать во второстепенных классах свои методы для обработки ивентов. Заводите под ивенты новые классы-хадлеры. Это облегчит их дальнейшую поддержку и поможет исключить ситуации, когда вы случайно удалите метод, который будут использовать сторонние плагины. Эта рекомендация не касается плагинов.

Подписка в плагинах:

В plugin.php добавляете ключ handlers, в который добавляете ключ *. Под этим ключом хранятся новые wildcard обработчики.

Пример

return array(
    'name'     => 'debug',
    '...',
    'handlers' => array(
        '*' => array(
            array(
                'event_app_id' => 'event_ app_id',
                'event'        => 'event_name',
                'class'        => 'app_idYouPluginNamePlugin',
                'method'       => 'eventMethod'
            )
        )
    ),
);

Если вы в плагине подпишитесь на другое приложение, то в результирующем массиве это будет отображено так:

$result['app_id-plugin_id-plugin] = result;
//реальный код
$result['shop-shopdebug-plugin] = array('i result')

Кастомные обработчики


Теперь можно добавить обработчик во время выполнения скрипта. Он не кешируется и живет только во время скрипта. Практической пользы на постоянной основе это не несет, но может быть полезно во время разработки и тестирования.  Не используйте его в продуктовом коде. (заблокировано в смарти).

Принцип работы:
Если в порядке выполнения скрипта будет добавлен кастомный обработчик, то с этого момента и до конца выполнения скрипта он будет доступен в waEvent. Кастомный обработчик содержит экземпляр класса, подключение и инициализация которого не ответственность waEvent. Т.е. вам сами нужно в поток подключить файл если он не доступен через автолоад и инициализировать объект. Для кастомного обработчика вызываются все методы в отличии от обработчиков приложений и плагинов. В результирующем массиве они будут храниться под ключом имя_класса_имя_метода-plugin

Как вызывать:

waEvent:addCustomHandler($handler)

Сигнатура:

$handler = array(
    'object' => object', //Экземпляр нужного вам класса 
    'method' =>'название метода' || array('название метода 1', 'название метода 2'),
    'event' => 'Имя ивента',
);

Пример:

$handler = array(
    'object' => new someCustomClass(),
    'method' =>'execute',
    'event' => 'event_name',
);
waEvent:addCustomHandler($handler)


Дополнительное описание waEvent:

Запуск в обход waSystem

$event_class = new waEvent($event_app_id, $name, $options);
$result = $event_class->run($params);

Принцип работы

При первом вызове обходит все приложения и плагины включенные в системе и собирает обработчики. Если в обработчиках содержатся форматирования ошибки, то такие обработчики игнорируются. А ошибки выполнения записываются в waLog. (при условии что включен дебаг режим).
Обработчики сохраняются в self::$handlers. Если event_app_id не определен, то будет сохранен под wildcard приложением. Если у обработчика имя ивента это маска или регулярное выражение, то такой обработчик сохраняется под wildcard ивентом.

Классическое сохранение:
self::$handlers['app_id']['event_name'][]
и новое 
self::$handlers['app_id']['*'][]
self::$handlers['*']['*'][]

После сборка обработчики будут закешированы в wa-cache (При условии что не объявлена константа). 

Дальше объединяются все обработчки подходящие под условия. Из wildcard приложений и точного приложения, берутся wildcard ивенты и точные ивенты.

$handlers = array_merge(
    ifset(self::$handlers, $this->event_app_id, $this->name, array()),
    ifset(self::$handlers, $this->event_app_id, '*', array()),
    ifset(self::$handlers, '*', $this->name, array()),
    ifset(self::$handlers, '*', '*', array()) //Why, why Mr. Anderson? Think again, you do not need to subscribe to all the hooks
);

Далее по ним проходит цикл и собирает результаты.

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

Логирование времени исполнения обработчиков

Появилась возможность логировать время, которое тратит каждый обработчик на выполнение кода. Это поможет найти плагины (или системный код) которые тормозят на ивентах.

Чтобы включить логирование надо себе в куки добавить ключ event_log_execution со значением 1 и быть юзером бекенда. Защита с помощью юзера бекенда требуется чтобы оградить сайт от различного вида жуликов, которые могут включить логирование и съедать место на жестком диске.

После добавления ключа и авторизации на сайте все обработчики, начнут сохранятся по адресу wa-log/webasyst/waEventExecutionTime.log.

Формат блока логов:

===Start log block===
Recorded: Имя юзера

array (
    имя_ивента =>
        array (
            0 =>
                array (
                    'app_id' => 'crm', //приложение в котором находится обработчик
                    'plugin_id' => 'yandex', //плагин, который подписался на обработчик
                    'regex' => '/backend_header/', //имя ивента в формате регулярного выражения на который подписался плагин/приложение 
                    'file' => 'webasyst.backend_header.handler.php', //Если есть, имя файла
                    'class' => 'crmWebasystBackend_headerHandler', //Имя класса, который нужно вызвать
                    'method' =>
                        array (
                            0 => 'execute', // методы которые нужно вызвать
                        ),
                    'execution_time' => 0.0188, // время выполнения данного обработчика в секундах
                ),
        ),
)

===End log block==="

Отключение кеша:

wa-config/SystemConfig.class.php требуется объявить константу WA_EVENT_CLEAR_CACHE

Очистка кеша:

waEvent::clearCache();

Чтобы очистить обработчики, которые сохранены в wa-cache 

waEvent::reset();

Чтобы очистить обработчики, которые находятся в оперативной памяти

46 ответов

  • 1
    Максим Сердюков 13 декабря 2018 15:31 #

    прототип класса доступен в гите. Полноценная версия будет в следующем обновлении фреймворка. Если есть какие-то вопросы по принципу работы класса, пишите в комментарии, я постараюсь ответить.

  • 1
    enso_studio@mail.ru 13 декабря 2018 16:18 #
    В plugin.php добавляете ключ handler.
    'handlers' => array(
    

    почему этот текст тут а не в базе знаний?

    • +1
      Максим Сердюков Максим Сердюков 13 декабря 2018 16:49 #

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

      • +1
        enso_studio@mail.ru enso_studio@mail.ru 14 декабря 2018 18:31 #

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

        И ошибку в тексте исправьте.  

    • +2
      Di Elshin Di Elshin Webasyst 13 декабря 2018 16:50 #

      waEvent пока что живёт в GitHub и доступен только разработчикам.

      Когда он начнёт поставляться в стабильной версии Фреймворка — появится соответствующая статья в документации.

  • 1
    enso_studio@mail.ru 13 декабря 2018 16:21 #

    Методы вызываются из главного класса вашего плагина. Они должны быть публичными и не статичными.

    учитывая у вас везде в документации навязвались статические хендлеры, то не возникнет ли проблем с совместимостью? почему бы просто не использовать callable формат?

  • 4
    Eugen Nichikov 13 декабря 2018 17:58 #

    Раз пошла такая пьянка, может добавите запуск произвольных событий в тему дизайна? Тут писал под старый формат, но можно и переделать под новый.

    • +1
      Максим Сердюков Максим Сердюков 13 декабря 2018 18:52 #

      Евгений, напишите пожалуйста, как можно более подробный список того, как вы будете это использовать и какой профит это может принести. Потому что сейчас на одной чаше весов стоят риски с безопасностью + хаос который смогут наводить плагины в темах дизайна, которые не адаптированы к результатам работы плагина(а виноваты будем мы и расхлебывать наша поддержка). А на второй чаше призрачная гибкость плагинов. Нужен какой-то план и что-то убедительное, чтобы это сделать.

      • +2
        Eugen Nichikov Eugen Nichikov 13 декабря 2018 19:20 #

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

        2. До введения wildcard ивентов написал бы, что рисков с хаосом не должно быть: вызываем ивент с префиксом custom_ (или любым другим), и на 99% никто "случайно" на такое не подпишется. Так что даже вопроса не было бы.

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

        Грубо говоря, вернуть во все ивенты <h1>test</h1>  == сломаем сайт.

        3. Не призрачная гибкость плагинов, а вполне разумная, и красивая замена кода

        {* проверяем существование плагина *}
        {if class_exists('shopTestPlugin')}
          {* допустим, плагин отдельно в настройках можно включить... такое часто надо *}
          {* и для усугубления ситуации... раньше в плагине не было такой проверки :) *}
          {if method_exists('shopTestPlugin', 'enabled')}
            {if shopTestPlugin::enabled()}
              {shopTestPlugin::doSmth()}
            {/if}
          {/if}
        {/if}

        на

        {$wa->event('shop', 'test_plugin_do_thms')}

        Код аккуратно впишется в тему дизайна. И скорее служит именно для гибкости тем.

        А также при установке кодов "сезонных" плагинов типа падающих снежинок не вызовет ошибки после удаления.

        P.S. frontend_head для Сайта уже завезли? А то разработчики тем могли бы также таким кодом сделать ему замену, а плагиноделы уже бы подписались на custom_frontend_head.

        • +1
          Максим Сердюков Максим Сердюков 14 декабря 2018 08:11 #

          Из того что я вижу, вам не глобальный ивент нужен, а возможность дернуть конкретный плагин. Потому что если 3 разработчика подпишутся на одно и тоже имя ивента (Один сделал, другим понравилось), то все опять перейдет на ветки ифов.
          + Во всех наших шоп фронтенд экшенах есть ивенты и я не вижу случая, когда надо выстраивать конструкцию 

          {* проверяем существование плагина *}
          {if class_exists('shopTestPlugin')}
            {* допустим, плагин отдельно в настройках можно включить... такое часто надо *}
            {* и для усугубления ситуации... раньше в плагине не было такой проверки :) *}
            {if method_exists('shopTestPlugin', 'enabled')}
              {if shopTestPlugin::enabled()}
                {shopTestPlugin::doSmth()}
              {/if}
            {/if}
          {/if}

          Но вижу проблему получить результат конкретного плагина из результирующего массива в нужном месте страницы.

          • +1
            Александр Тарасенко Александр Тарасенко 14 декабря 2018 08:18 #

            Потому что если 3 разработчика подпишутся на одно и тоже имя ивента (Один сделал, другим понравилось), то все опять перейдет на ветки ифов.

            Не перейдет если они подпишутся одинакова, теме без разницы какой плагин сработал - главное он вернул ожидаемые данные. Но вот за этим уже вам придется следить или через модерацию или через стандартизацию

            + Во всех наших шоп фронтенд экшенах есть ивенты и я не вижу случая, когда надо выстраивать конструкцию

            Вот тут немного непонятно, о чем идет речь, на самом деле приведенная выше конструкция присутствует во всем темах! 

            • +1
              Максим Сердюков Максим Сердюков 14 декабря 2018 08:47 #

              Александр, как можно стандартизировать или модерировать то, что отображается в теме дизайна? Представим кнопку "сделать удобно" с большим количеством js, которая сделана под тему дефолт. А потом вы переключаетесь на другую тему и получаете эту же кнопку, но она работает совершенно не так так, или вообще весь js упал потому что не нашел нужные селекторы. Стандарты и модерация тут не помогут. Или они станут настолько медленным, что плагины будут публиковаться через года. 


              Вот тут немного непонятно, о чем идет речь, на самом деле приведенная выше конструкция присутствует во всем темах!

              Я говорю о том, что при открытии каждой базовой страницы магазина кидается какой-нибудь ивент. 
              К примеру: 

              wa()->event('frontend_compare', $params)
              

              Вы можете там разместить результат работы вашего плагина и получите его в смарти. И я пока не понимаю зачем делать эти конструкции во всех темах. Пришлите пожалуйста реальный кейс, где вы не смогли использовать базовые ивенты.

              • +1
                Александр Тарасенко Александр Тарасенко 14 декабря 2018 09:14 #

                По первому пункту, так не отображение стандартизовывать, а формат входящих параметров и формат результата, по принципу черного ящика, без разницы как работает плагин или приложение или там сервис, есть формат вызова, и формат получения результата, все. Больше ничего не нужно, тема знает что и как запросить, и знает какой результат будет возвращен. Но это отдельная дискуссия как и стандартизация селекторов - пока со стороны webasyst не будет жестких стандартов и требований, будет хаос, но оставим этот момент, более интересна вторая часть.


                Вы об этих хуках: https://developers.webasyst.ru...? Или мы говорим о разных вещах?

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

                Второй кейс, есть плагин Подарки, задача добавить к товару ярлык Подарок, сейчас реализация такая:

                {if class_exists('shopAddgiftsPlugin') && method_exists('shopAddgiftsPlugin', 'badgeHtml')}
                {$badges = shopAddgiftsPlugin::badgeHtml($p)}
                {else}
                {$badges = $wa->shop->badgeHtml($p.badge)}
                {/if}

                как с помощью базовых ивентов это реализовать?

                • +1
                  Максим Сердюков Максим Сердюков 14 декабря 2018 09:51 #

                  Ну вот вы сами же представляете, какой это объем работы по стандартизации  и модерации. На это годы могут уйти. 

                  Вы можете через ивент frontend_product получить такой же результат. Он вызовет ваш статический метод (хоть я и написал, что методы должны быть не статические). Но от ифа все равно не получится избавиться, я согласен.

                  В любом случае в ближайшее время реализовать группировку, стандартизацию и все остальное что нужно, чтобы эта фича заработала не представляется возможным.

                  Ну и делать метод хэлпера, который время от времени будет экономить 2 строчки кода бессмысленно.

                  А эту конструкцию

                  {* проверяем существование плагина *}
                  {if class_exists('shopTestPlugin')}
                    {* допустим, плагин отдельно в настройках можно включить... такое часто надо *}
                    {* и для усугубления ситуации... раньше в плагине не было такой проверки :) *}
                    {if method_exists('shopTestPlugin', 'enabled')}
                      {if shopTestPlugin::enabled()}
                        {shopTestPlugin::doSmth()}
                      {/if}
                    {/if}
                  {/if}

                  Замените на 

                  {if is_callable(['shopTestPlugin', 'doSmth']) && someClass::enable()}
                      {shopTestPlugin::doSmth()} 
                  {/if}

                  • +1
                    Александр Тарасенко Александр Тарасенко 14 декабря 2018 10:03 #

                    В любом случае в ближайшее время реализовать группировку, стандартизацию и все остальное что нужно, чтобы эта фича заработала не представляется возможным.

                    Жаль конечно, хотя при желание можно начать с малого и дальше расширять, стандартизируйте изображение для категорий потом еще что то и т.д.


                    На самом деле если бы был хук frontent_badges входящий параметр id товара, результат массив с наклейками - то вот оно решение, и не нужно вызывать {$badges = $wa->shop->badgeHtml($p.badge)} и прочие другие плагины, вызвал хук - получил результат, вывел как нужно.


                    Возможно причина в том что стандартных хуков очень мало, если бы они охватывали весь функционал то и данных бы проблем не было. 

                  • +2
                    Syrnik.com Syrnik.com 14 декабря 2018 11:51 #

                    Лучше бы в waViewHelper добавили проверку на наличие плагина и "включенность". Потому как при обоих вариантах проверки, приведенных выше, будет ошибка если плагин установлен, но в Инсталлере отключен.

                    И проверку не только плагина, но и приложений тоже

                    • +1
                      Eugen Nichikov Eugen Nichikov 14 декабря 2018 13:09 #

                      Разве классы попадают в автозагрузку, если плагин/приложение отключены?

                      Плюс есть ещё внутренние опции плагинов, которые отдельно включают/выключают некоторые функции. С этим проверка в waViewHelper не поможет.

                      • +2
                        Алексей Алексей Webasyst 14 декабря 2018 14:50 #

                        В рамках приложения да - автозагрузка собирает по папкам.
                        Поэтому что-то типа 

                        wa('shop');
                        $obj = new shopYandexmarketPlugin(1);

                        сработает, даже если плагин выключен в инсталлере.
                        И плагины будут вызываться хелперами в теме {shopMyPlugin::getHtml()} даже если отключены.

                        • +1
                          Eugen Nichikov Eugen Nichikov 14 декабря 2018 15:14 #

                          Оу, спасибо! Не вникал. Вот ещё камень в огород хелперов.

                          Ивенты лишены этого недостатка.

                      • +1
                        km km 14 декабря 2018 18:47 #

                        Плюс есть ещё внутренние опции плагинов, которые отдельно включают/выключают некоторые функции. С этим проверка в waViewHelper не поможет.

                        можно было бы доьавить интерфейс для плагинов, где обязали бы такой метод реализовать)

                  • +1
                    Eugen Nichikov Eugen Nichikov 14 декабря 2018 13:00 #

                    Не нужно ничего стандартизировать. Просто дайте возможность использовать вместо статических хелперов такие ивенты.

                    Кто-то продолжит пользоваться статическими, кто-то перейдёт на новый формат. Кто-то реализует нужный и удобный хук, который всем понравится. Что в этом плохого.

                    Есть ещё один "идеальный пример" - это кнопки "Купить в 1 клик".

                    {if is_callable(['shopOneclickPlugin', 'button']) && shopOneclickPlugin::enable()}
                        {shopOneclickPlugin::button()} 
                    {/if}
                    {if is_callable(['shopBuy1clickPlugin', 'button']) && shopBuy1clickPlugin::enable()}
                        {shopBuy1clickPlugin::button()} 
                    {/if}
                    {if is_callable(['shopTwoclickPlugin', 'button']) && shopTwoclickPlugin::enable()}
                        {shopTwoclickPlugin::button()} 
                    {/if}

                    станет

                    {$wa->event('универсальное и удобное событие для однокликов')}

                    Тема, в конце концов, не должна "знать" о том установлен ли плагин, включён ли он.

                    "Живые" примеры "хаоса" и без произвольных ивентов (да простит меня Владимир):

                  • +1
                    enso_studio@mail.ru enso_studio@mail.ru 15 декабря 2018 05:33 #

                    Можно добавить плагины в theme.xml requirements:

                    <requirement property="plugin.app_id.plugin_id" value="1.0.0" strict="true">

                    и ViewHelper'ы плагинов:

                    {if $wa->app->plugin}
                       {$wa->app->plugin->method()}
                    {else}
                       {* действие по умолчанию *}
                    {/if}

                    или smarty метод:

                    {wa_helper id='app.plugin.method' params=['barge' => ''] alt='{$res = $wa->shop->badgeHtml($params.badge)}' assign='res'}

                    alt - smarty строка выполняемая если  плагин неактивен, assign - имя переменной в которую сохраняется результат.

                    Чтобы вернуть результат alt'а сохраняем результат в переменную с названием указанным в assign.


                • +1
                  Алексей Алексей Webasyst 14 декабря 2018 10:27 #

                  А если использовать другой подход и не заставлять тему делать вызов.
                  Вы как разработчик темы просто в нужном месте добавляете переменную {if $custom_plugin_cityselect|default:false}...{/if}, а разработчик плагина просто присваивает эту переменную для вывода?

                  • +1
                    Александр Тарасенко Александр Тарасенко 14 декабря 2018 10:45 #

                    Как вариант, но суть та-же, это немного смягчит проблему адаптацию своих-же плагинов в свои же темы дизайна)) да и то не везде, а другие разработчики будут так-же использовать кто что

      • +2
        Александр Тарасенко Александр Тарасенко 13 декабря 2018 21:02 #

        Извините, но как раз именно сейчас и есть хаос )

        Как разработчики тем приходится в темах городить данные условия:
        {if class_exists('shopCatimgPlugin')}
        {$result = shopCatimgPlugin::get_image($cat.id, true)}
        {/if}
        ...
        {if class_exists('shopCategoryImagesPlugin')}
        {$result = shopCategoryImagesPlugin::getCategoryLittleThumbUrl($cat.id)}
        {/if}
        ...
        {if class_exists('shopWmimageincatPlugin')}
        {$result = shopWmimageincatPlugin::getCategoryImage($cat.id, 'icon')}
        {/if}

        А плагинов все больше и больше, а пользователи все просят и просят интегрировать плагины )

        Одно из преимуществ может быть некая стандартизация однотипных плагинов, например избитые изображения для категорий  

        {$result = $wa->event('shop.category_image', ['id':$category.id, 'type':'icon'])}


        Далее поддержка темами сторонних плагинов (которые не описываются хуками) например для выбора города в теме сейчас приходится изворачиваться так:

        {foreach $frontend_header as $_plugin_id=>$_}
             {if $_plugin_id == 'cityselect-plugin'}{$_}{/if}
        {/foreach}

        Если однотипных плагинов несколько, например "Купить в 1 клик":

        {$move_plugins_cart[] = 'quickorder'}
        {$move_plugins_cart[] = 'storequickorder'}
        {$move_plugins_cart[] = 'buy1click'}

        ...

        {* @event frontend_product.%plugin_id%.cart *}
        {foreach $frontend_cart as $_plugin => $_}
        {$_plugin_id = str_replace('-plugin', '', $_plugin)}
        {if in_array($_plugin_id, $move_plugins_cart)}
        <div class="col-auto mb-3 b-{$_plugin_id}--cart">{$_}</div>
        {/if}
        {/foreach}

        Только Вы как разработчики платформы можете принудить к стандартизации, однако почему-то всячески этого избегаете. Как вы придумаете и скажете так и будет

        • +1
          Eugen Nichikov Eugen Nichikov 14 декабря 2018 13:04 #

          Оу, недочитал, а тут уже и был пример однокликов.

          Great minds think alike.

    • +1
      enso_studio@mail.ru enso_studio@mail.ru 14 декабря 2018 21:17 #

      Моя версия:

      class waAppViewHelper
      {
          /**
           * @param string $name Event name.
           * @param array|null $params Parameters passed to event handlers.
           * @param bool $concat_result Implode result?
           * @return array|string
           */
          public function event($name, &$params = null, $concat_result = false)
          {
              $result = (array) $this->wa()->event('custom.'.$name, $params);
              if ($concat_result) {
                  return implode($result);
              };
              return $result;
          }
      }

      Возвращать null неправильно т.к. пользователь ожидает результат определенного типа и могут возникнуть ошибки.

      Кроме того я перенес метод в waAppViewHelper - не потребуются проверять существует ли приложение.


      • +1
        Eugen Nichikov Eugen Nichikov 14 декабря 2018 21:37 #

        null было под вопросом. Главное, чтобы идею вообще рассматривали.

        Ну и я за $concat_result = true по умолчанию.

        Т.к. большинство хелперов или вставляют HTML-код

        {shopMessageboxPlugin::display(1)}

        или обрабатывают входные данные

        {shopFlexdiscountHelper::workupProducts(&$products)}

        • +1
          Алексей Алексей Webasyst 15 декабря 2018 08:54 #

          Входные данные наверно уже не нужны

          {shopFlexdiscountHelper::workupProducts(&$products)}

          т.к. легко обрабатывается в самом плагине через хук view_products. Аналогично и с другими коллекциями. Поэтому для них шаблон уже не потребуется править.

          • +1
            Eugen Nichikov Eugen Nichikov 15 декабря 2018 14:46 #

            Это как пример, который я смог вспомнить и найти. Думаю, можно подобрать и более актуальный пример. Сути не меняет.

  • 1
    km 14 декабря 2018 18:53 #

    Вот тут не понял

    $result['app_id-plugin_id-plugin] = result;
    //реальный код
    $result['shop.shopdebug-plugin] = array('i result')

  • 1
    Den 10 октября 2019 02:56 #

    До перехода на SS8 у меня следующее условие для проверки на существование пользовательского класса из shopCustom.class.php

    {if class_exists(getContactCategoryDiscount)}
    ...
    {/if}

    Теперь же эта проверка не работает, подскажите пожалуйста на что её заменить?

  • 1
    Markus 10 октября 2019 08:43 #

    он то class_exists но выключен ли он или нет?

    • +1
      Den Den 10 октября 2019 12:20 #

      Отбой. Я вчера совсем уже заработался: с помощью class_exists проверял не название класса, а название функции внутри него. Так что всё работает как и работало.

Добавить ответ

Чтобы добавить комментарий, зарегистрируйтесь или войдите