Переопределение методов модулей с помощью ...Hook'ов!
В LiveStreet 0.4 появилась возможность переопределять не только целиком модули, но и отдельные методы. Это позволить разным плагинам бесконфликтно переопределять разные методы одного модуля.
Принцип действия этого механизма основан на Hook'ах:
Пример:
Список методов для делегирования:
Важное замечание:
Если на module_ModuleName_MethodName_before висит несколько хуков, то сначала они разбиваются на две группы: стандартные и делегирующие. Внутри каждой группы хуки сортируются по приоритету, затем выполняется стандартная группа и только затем делегирующая. Причем в делегирующей группе выполняется только первый хук, остальные отбрасываются для исключения конфликтов.
Принцип действия этого механизма основан на Hook'ах:
- Вызов каждого метода сопровождается выполнением хуков — module_ModuleName_MethodName_before и module_ModuleName_MethodName_after, соответственно ДО и ПОСЛЕ вызова метода модуля. В первом случаи в хук передаются параметры вызова метода, во втором передается результат выполнения метода модуля.
- На module_ModuleName_MethodName_before можно повесить специальный хук — delegate, результат выполнения которого и будет «результатом» выполнения метода модуля
Пример:
<?php
class HookTest extends Hook {
public function RegisterHook() {
$this->AddDelegateHook('module_text_parser_before','testHook',__CLASS__,-3);
}
public function testHook($aVars) {
return 'Topic text > '.$aVars[0];
}
}
?>
Здесь происходит переопределение метода Parser модуля Text, в результате к тексту топика будет добавлена строчка 'Topic text > ', при этом исходный метод (Text_Parser()) выполнен не будет.Список методов для делегирования:
Hook_AddDelegateModule($sName,$sCallBack,$iPriority=1)
Hook_AddDelegateFunction($sName,$sCallBack,$iPriority=1)
Hook_AddDelegateHook($sName,$sCallBack,$iPriority=1,$aParams=array())
Использование этих актуально только для хуков методов модулей.Важное замечание:
Если на module_ModuleName_MethodName_before висит несколько хуков, то сначала они разбиваются на две группы: стандартные и делегирующие. Внутри каждой группы хуки сортируются по приоритету, затем выполняется стандартная группа и только затем делегирующая. Причем в делегирующей группе выполняется только первый хук, остальные отбрасываются для исключения конфликтов.
20 комментариев
Я бы в таком случае иначе сделал бы. Предлагаю завести некий контейнер статуса выполнения метода, и в нем указывать, надо продолжать выполнение цепочки хуков и самого метода или нет. Плюс — вызов всех параметров по ссылке. Тогда, приведенный выше пример мог бы выглядеть так:
Возвращаем обработанный текст и прекращаем его дальнейшую обработку.
Но если хотим продолжить обработку после нашего хука, то так:
А вот тут мы и текст меняем (меняя содержимое передаваемого аргумента), и позволяем его обрабатывать дальше.
1. выполняться все стандартные хуки
2. выполнение хука произойдет до выполнения метода или его делегата, т.к. хук прописан как _before
в твоём подходе ни 1, ни 2 пункт не выполняются, что посеет хаос :)
п.1 В предлагаемом мной варианте нет деления на «стандартные» и «делегирующие». Любой хук в любое время (в зависимости от логики его работы) может стать, фактически, делегирующим. Когда это может быть полезно: напр., если в хуке проверяется какое-то условие (например, при добавлении топика), и это условие не выполнено и нужно прервать процесс. И в этом случае не играет особой роли, какие хуки выполнились, а какие нет, топик добавлять нельзя.
В изложенном в топике варианте все хуки будут выполняться всегда, даже если этого не нужно.
Если же никакой хук не посчитает нужным прервать выполнение последующих хуков, то оба пункта выполняются без проблем. А хаос — его, при желании, можно в любом месте создать :)
именно, только не все, а стандартные. Один хук не должен влиять на выполнение других(например хуки разных плагинов), кроме случая когда несколько хуков делегирующие. Этот случай аналогичем тому, когда разные плагины делегируют один и тот же модуль.
если AddDelegateHook переопределяет метод модуля, то какую такую функцию переопределяет AddDelegateFunction?
вызывает хук module_Topic_GetTopicsByFilter_before, а
вообще никакого хука не вызывает, как дальше жить?
первое — вызов метода модуля Topic
второе — вызод метода текущего класса, то есть пока еще не известно, что это модуль.