title: what is the purpose of having function exec() in Hook.php in prestashop
body: <p>In the <code>Header.tpl</code> file there is a hook <code>{$HOOK_TOP}</code> which contains all the header part including menu, search etc... You can check that in this URL </p>
  
  <p>In the <code>FrontController</code> it shows... <code>'HOOK_TOP' =&gt; Hook::exec('displayTop')</code>,
  it means in the Hook page there is a function called <code>exec()</code>. But I cannot understand the code properly in the <code>exec()</code> call.</p>
  
  <p>It tells it <em>Execute modules for specified hook</em>. When I searched for "<em>displayTop</em>" I got a module name called <code>blocktopmenu.php</code>.</p>
  
  <p>Execution only goes through 2 functions:</p>
  
  <pre><code>    public function hookDisplayTop($param)
      {
          $this-&gt;user_groups =  ($this-&gt;context-&gt;customer-&gt;isLogged() ? $this-&gt;context-&gt;customer-&gt;getGroups() : array(Configuration::get('PS_UNIDENTIFIED_GROUP')));
          $this-&gt;page_name = Dispatcher::getInstance()-&gt;getController();
          if (!$this-&gt;isCached('blocktopmenu.tpl', $this-&gt;getCacheId()))
          {
              $this-&gt;makeMenu();
              $this-&gt;smarty-&gt;assign('MENU_SEARCH', Configuration::get('MOD_BLOCKTOPMENU_SEARCH'));
              $this-&gt;smarty-&gt;assign('MENU', $this-&gt;_menu);
              $this-&gt;smarty-&gt;assign('this_path', $this-&gt;_path);
          }
  
          $this-&gt;context-&gt;controller-&gt;addJS($this-&gt;_path.'js/hoverIntent.js');
          $this-&gt;context-&gt;controller-&gt;addJS($this-&gt;_path.'js/superfish-modified.js');
          $this-&gt;context-&gt;controller-&gt;addCSS($this-&gt;_path.'css/superfish-modified.css');
  
          $html = $this-&gt;display(__FILE__, 'blocktopmenu.tpl', $this-&gt;getCacheId());
          //print_r($html);//exit;
          return $html;
      }
  </code></pre>
  
  <p>and</p>
  
  <pre><code>protected function getCacheId($name = null)
  {//echo"asdasdsad";exit;
      parent::getCacheId($name);
      $page_name = in_array($this-&gt;page_name, array('category', 'supplier', 'manufacturer', 'cms', 'product')) ? $this-&gt;page_name : 'index';
      return 'blocktopmenu|'.(int)Tools::usingSecureMode().'|'.$page_name.'|'.(int)$this-&gt;context-&gt;shop-&gt;id.'|'.implode(', ',$this-&gt;user_groups).'|'.(int)$this-&gt;context-&gt;language-&gt;id.'|'.(int)Tools::getValue('id_category').'|'.(int)Tools::getValue('id_manufacturer').'|'.(int)Tools::getValue('id_supplier').'|'.(int)Tools::getValue('id_cms').'|'.(int)Tools::getValue('id_product');
  }
  </code></pre>
  
  <p>But this public function <code>hookDisplayTop($param)</code> never gets called in the whole folder anywhere. I searched it but never found it in any file.</p>
  
  <p>The <code>exec()</code> function shows below</p>
  
  <pre><code>public static function exec($hook_name, $hook_args = array(), $id_module = null, $array_return = false, $check_exceptions = true)
      {
  
          // Check arguments validity
          if (($id_module &amp;&amp; !is_numeric($id_module)) || !Validate::isHookName($hook_name))
              throw new PrestaShopException('Invalid id_module or hook_name');
  
          // If no modules associated to hook_name or recompatible hook name, we stop the function
  
          if (!$module_list = Hook::getHookModuleExecList($hook_name))
              return '';
  
          // Check if hook exists
          if (!$id_hook = Hook::getIdByName($hook_name))
              return false;
  
          // Store list of executed hooks on this page
  
          Hook::$executed_hooks[$id_hook] = $hook_name;
      //  print_r(Hook::$executed_hooks);exit;
  
          $live_edit = false;
          $context = Context::getContext();
          if (!isset($hook_args['cookie']) || !$hook_args['cookie'])
              $hook_args['cookie'] = $context-&gt;cookie;
          if (!isset($hook_args['cart']) || !$hook_args['cart'])
              $hook_args['cart'] = $context-&gt;cart;
  
          $retro_hook_name = Hook::getRetroHookName($hook_name);
  //print_r($hook_name);exit;
          // Look on modules list
          $altern = 0;
          $output = '';
          foreach ($module_list as $array)
          {
              // Check errors
              if ($id_module &amp;&amp; $id_module != $array['id_module'])
                  continue;
              if (!($moduleInstance = Module::getInstanceByName($array['module'])))
                  continue;
  
              // Check permissions
              if ($check_exceptions)
              {
                  $exceptions = $moduleInstance-&gt;getExceptions($array['id_hook']);
                  $controller = Dispatcher::getInstance()-&gt;getController();
  
                  if (in_array($controller, $exceptions))
                      continue;
  
                  //retro compat of controller names
                  $matching_name = array(
                      'authentication' =&gt; 'auth',
                      'compare' =&gt; 'products-comparison',
                      );
                  if (isset($matching_name[$controller]) &amp;&amp; in_array($matching_name[$controller], $exceptions))
                      continue;
                  if (Validate::isLoadedObject($context-&gt;employee) &amp;&amp; !$moduleInstance-&gt;getPermission('view', $context-&gt;employee))
                      continue;
              }
  
              // Check which / if method is callable
              $hook_callable = is_callable(array($moduleInstance, 'hook'.$hook_name));
              $hook_retro_callable = is_callable(array($moduleInstance, 'hook'.$retro_hook_name));
              if (($hook_callable || $hook_retro_callable) &amp;&amp; Module::preCall($moduleInstance-&gt;name))
              {
                  $hook_args['altern'] = ++$altern;
  
                  // Call hook method
                  if ($hook_callable)
                      $display = $moduleInstance-&gt;{'hook'.$hook_name}($hook_args);
                  else if ($hook_retro_callable)
                      $display = $moduleInstance-&gt;{'hook'.$retro_hook_name}($hook_args);
                  // Live edit
                  if (!$array_return &amp;&amp; $array['live_edit'] &amp;&amp; Tools::isSubmit('live_edit') &amp;&amp; Tools::getValue('ad') &amp;&amp; Tools::getValue('liveToken') == Tools::getAdminToken('AdminModulesPositions'.(int)Tab::getIdFromClassName('AdminModulesPositions').(int)Tools::getValue('id_employee')))
                  {
                      $live_edit = true;
                      $output .= self::wrapLiveEdit($display, $moduleInstance, $array['id_hook']);
                  }
                  else if ($array_return)
                      $output[] = $display;
                  else
                      $output .= $display;
              }
          }
          if ($array_return)
              return $output;
          else
              return ($live_edit ? '&lt;script type="text/javascript"&gt;hooks_list.push(\''.$hook_name.'\'); &lt;/script&gt;
                  &lt;div id="'.$hook_name.'" class="dndHook" style="min-height:50px"&gt;' : '').$output.($live_edit ? '&lt;/div&gt;' : '');// Return html string
      }
  </code></pre>