*/ class Hook extends AbstractSmartyPlugin { private $dispatcher; /** @var Translator */ protected $translator; /** @var Module */ protected $smartyPluginModule = null; /** @var array */ protected $hookResults = array(); /** @var array */ protected $varstack = array(); /** @var bool debug */ protected $debug = false; public function __construct($debug, ContainerAwareEventDispatcher $dispatcher) { $this->debug = $debug; $this->dispatcher = $dispatcher; $this->translator = $dispatcher->getContainer()->get("thelia.translator"); $this->hookResults = array(); } /** * Generates the content of the hook * * {hook name="hook_code" var1="value1" var2="value2" ... } * * This function create an event, feed it with the custom variables passed to the function (var1, var2, ...) and * dispatch it to the hooks that respond to it. * * The name of the event is `hook.{context}.{hook_code}` where : * * context : the id of the context of the smarty render : 1: frontoffice, 2: backoffice, 3: email, 4: pdf * * hook_code : the code of the hook * * The event collects all the fragments of text rendered in each modules functions that listen to this event. * Finally, this fragments are concatenated and injected in the template * * @param array $params the params passed in the smarty function * @param \TheliaSmarty\Template\SmartyParser $smarty the smarty parser * * @return string the contents generated by modules */ public function processHookFunction($params, &$smarty) { $hookName = $this->getParam($params, 'name'); $module = intval($this->getParam($params, 'module', 0)); $moduleCode = $this->getParam($params, 'modulecode', ""); $type = $smarty->getTemplateDefinition()->getType(); $event = new HookRenderEvent($hookName, $params, $smarty->getTemplateVars()); $event->setArguments($this->getArgumentsFromParams($params)); $eventName = sprintf('hook.%s.%s', $type, $hookName); // this is a hook specific to a module if (0 === $module && "" !== $moduleCode) { if (null !== $mod = ModuleQuery::create()->findOneByCode($moduleCode)) { $module = $mod->getId(); } } if (0 !== $module) { $eventName .= '.' . $module; } $this->getDispatcher()->dispatch($eventName, $event); $content = trim($event->dump()); if ($this->debug && $smarty->getRequest()->get('SHOW_HOOK')) { $content = self::showHook( $hookName, $params, $smarty->getTemplateVars() ) . $content; } $this->hookResults[$hookName] = $content; // support for compatibility with module_include if ($type === TemplateDefinition::BACK_OFFICE) { $content .= $this->moduleIncludeCompat($params, $smarty); } return $content; } /** * Call the plugin function module_include for backward compatibility. * * @param array $params the params passed in the smarty function * @param \TheliaSmarty\Template\SmartyParser $smarty the smarty parser * * @return string the contents generated by module_include function */ protected function moduleIncludeCompat($params, &$smarty) { $plugin = $this->getSmartyPluginModule(); $params = array( "location" => $this->getParam($params, 'location', null), "module" => $this->getParam($params, 'modulecode', null), "countvar" => $this->getParam($params, 'countvar', null) ); return $plugin->theliaModule($params, $smarty); } /** * get the smarty plugin Module * * @return Module the smarty plugin Module */ protected function getSmartyPluginModule() { if (null === $this->smartyPluginModule) { $this->smartyPluginModule = $this->dispatcher->getContainer()->get("smarty.plugin.module"); } return $this->smartyPluginModule; } protected function showHook($hookName, $params, $templateVars) { if (!\class_exists('\Symfony\Component\VarDumper\VarDumper')) { throw new \Exception('For use SHOW_HOOK, you can install dependency symfony/var-dumper'); } ob_start(); \Symfony\Component\VarDumper\VarDumper::dump([ 'hook name' => $hookName, 'hook parameters' => $params, 'hook external variables' => $templateVars ]); $content = ob_get_clean(); return << {$hookName} Show details
HTML; } /** * Process the content of the hook block. * * {hookblock name="hook_code" var1="value1" var2="value2" ... } * * This function create an event, feed it with the custom variables passed to the function (var1, var2, ...) and * dispatch it to the hooks that respond to it. * * The name of the event is `hook.{context}.{hook_code}` where : * * context : the id of the context of the smarty render : 1: frontoffice, 2: backoffice, 3: email, 4: pdf * * hook_code : the code of the hook * * The event collects all the fragments generated by modules that listen to this event and add it to a fragmentBag. * This fragmentBag is not used directly. This is the forhook block that iterates over the fragmentBag to inject * data in the template. * * @param array $params * @param string $content * @param \TheliaSmarty\Template\SmartyParser $smarty * @param bool $repeat * * @return string the generated content */ public function processHookBlock($params, $content, $smarty, &$repeat) { $hookName = $this->getParam($params, 'name'); $module = intval($this->getParam($params, 'module', 0)); // explicit definition of variable that can be returned $fields = preg_replace( '|[^a-zA-Z0-9,\-_]|', '', $this->getParam($params, 'fields', '') ); $fields = ('' !== $fields) ? explode(",", $fields) : []; if (!$repeat) { if ($this->debug && $smarty->getRequest()->get('SHOW_HOOK')) { $content = self::showHook($hookName, $params, $smarty->getTemplateVars()) . $content; } return $content; } $type = $smarty->getTemplateDefinition()->getType(); $event = new HookRenderBlockEvent($hookName, $params, $fields, $smarty->getTemplateVars()); $event->setArguments($this->getArgumentsFromParams($params)); $eventName = sprintf('hook.%s.%s', $type, $hookName); // this is a hook specific to a module if (0 !== $module) { $eventName .= '.' . $module; } $this->getDispatcher()->dispatch($eventName, $event); // save results so we can use it in forHook block $this->hookResults[$hookName] = $event->get(); } /** * Process a {forhook rel="hookname"} ... {/forhook} * * The forhook iterates over the results return by a hookblock : * * {hookblock name="product.additional"} * {forhook rel="product.additional"} *{$content}
*