Jump to content

How to place block to another hook without affecting source code of module


Peter Hajducek
 Share

Recommended Posts

Hello,

I need to place search block into footer of my theme without affecting source code of BlockSearch module to prevent complications when updating it. I didn't find any solution on PrestaShop forums, so I created my own:

I created hookFooter function in my own module:

public function hookFooter($params) {            
 include(_MODULE_DIR_.'blocksearch/blocksearch.php');
 $blocksearch = new BlockSearch();
 return $blocksearch->hookRightColumn($params);        
}



This way I can place search block into footer without affecting source code of Block search module. However, if I don't include blocksearch.php, class BlockSearch is not defined, yet. Therefore I have included it. Later PrestaShop included blocksearch.php again and it printed error, that I cannot redefine class BlockSearch. To prevent this, I had to modify source code of blocksearch.php and wrap class definition with if(!class_exists('BlockSearch')){}.

Now everything works great. However, I have 2 questions:

1) Does anyone have better solution for this?

2) If noone has better solution, I would propose to wrap all class definitions of modules with if(!class_exists('')){...}. What do you think?

Thanks,
Peter

Share this post


Link to post
Share on other sites

I've been using my plugins for this in 1.4 and it has the additional side-effect of being able to display the output of a block more than once if it makes sense to do so.

As an example, to get the cart to run and assign it's variables etc. without displaying anything you can use:

{capture name='cart_pre_force' assign='cart_block'}{plugin module='blockcart' hook='rightColumn'}{/capture}



Then you can use any of the smarty variables that the module assigns (e.g. $nb_total_products for the blockcart module ) anywhere on the page (or in any subsequent template). Later in the page rendering order (same or subsequent template) you can then just use:

{$cart_block}



To display the module's output. You would obviously unhook the module from it's default display location to prevent Prestashop trying to display it as a normal hooked module. Unfortunately the latest version, which supports smarty 3, is still in testing but it will be released soon with lots of other helpful goodies to make stunning 1.4 themes a breeze :)

Paul

Share this post


Link to post
Share on other sites

It would be better to use this:
return Module::getInstanceByName('blocksearch')->hookRightColumn($params);



Hi whitelighter,

thank you very much for such a quick answer. Could you please explain me what is the advantage of using this code?

Thanks,
Peter

Share this post


Link to post
Share on other sites

Hi Paul,

thank you for answer. Your code looks nice, but I am not sure if I understand it totally. I am looking for solution that allows me to place block in any hook I want without affecting the core or module code. Is it possible with plugin method or smarty 3?

Thanks,
Peter

Share this post


Link to post
Share on other sites

The mechanism I'm using would mean that to display the search block in the footer you would write:

{plugin module='blocksearch' hook='rightColumn'}



anywhere you want the block to display in (e.g. anywhere you care to place it in footer.tpl). No hooks, no changes to core files (except the overrides and additional class to support the functionality) and no manually coded modules - just edit the theme template and it's done.

If you wanted the search in both the header and footer, then you would capture the output as in the cart example above, and then display the variable in both template files. The only issue with doing that might be that there may be validation issues with the markup (id's used more than once for example).

Paul

Share this post


Link to post
Share on other sites

It would be better to use this:
return Module::getInstanceByName('blocksearch')->hookRightColumn($params);



Hi whitelighter,

thank you very much for such a quick answer. Could you please explain me what is the advantage of using this code?

Thanks,
Peter


It is always better to use the core functions.

Share this post


Link to post
Share on other sites

The mechanism I'm using would mean that to display the search block in the footer you would write:
{plugin module='blocksearch' hook='rightColumn'}



anywhere you want the block to display in (e.g. anywhere you care to place it in footer.tpl). No hooks, no changes to core files (except the overrides and additional class to support the functionality) and no manually coded modules - just edit the theme template and it's done.

If you wanted the search in both the header and footer, then you would capture the output as in the cart example above, and then display the variable in both template files. The only issue with doing that might be that there may be validation issues with the markup (id's used more than once for example).

Paul



This reminds me of a mod I did sometime ago:
http://www.prestashop.com/forums/viewthread/61808/third_party_modules/placing_modules_anywhere_in_the_tpl_files

Share this post


Link to post
Share on other sites

It would be better to use this:
return Module::getInstanceByName('blocksearch')->hookRightColumn($params);



Hi whitelighter,

thank you very much for such a quick answer. Could you please explain me what is the advantage of using this code?

Thanks,
Peter


It is always better to use the core functions.



Hi,

I have just checked method getInstanceByName(). It really looks nice, I will use it instead of my code. I am just wondering why developers of core do not wrap including module file, which redefines class and it prints php error. This is how it looks now:

   static public function getInstanceByName($moduleName)
   {
       if (!Tools::file_exists_cache(_PS_MODULE_DIR_.$moduleName.'/'.$moduleName.'.php'))
           return false;
       include_once(_PS_MODULE_DIR_.$moduleName.'/'.$moduleName.'.php');
       if (!class_exists($moduleName, false))
           return false;

       if (!isset(self::$_INSTANCE[$moduleName]))
           self::$_INSTANCE[$moduleName] = new $moduleName;
       return self::$_INSTANCE[$moduleName];
   }



How I would like to edit it

   static public function getInstanceByName($moduleName)
   {
       if (!Tools::file_exists_cache(_PS_MODULE_DIR_.$moduleName.'/'.$moduleName.'.php'))
           return false;
      // if file with class is already included, return its name
      if (class_exists($moduleName, false))
           return $moduleName;
       include_once(_PS_MODULE_DIR_.$moduleName.'/'.$moduleName.'.php');
       if (!class_exists($moduleName, false))
           return false;

       if (!isset(self::$_INSTANCE[$moduleName]))
           self::$_INSTANCE[$moduleName] = new $moduleName;
       return self::$_INSTANCE[$moduleName];
   }



What do you think? Is there another place where I should place this idea?

Thanks,
Peter

Share this post


Link to post
Share on other sites

Maybe you're looking for this:


Over Riding Module output

So to customise the out put of this module we can do one of two things. We can go straight into the /modules directory in the root of our prestashop install and select the module we wish to alter and then change the .tpl file within there. Or we can do it the more proper way and override the default module by making a directory under our /themes/newtheme/modules/ directory called NAME OF MODULE. The reason we do it the more proper "override" way is when we come to upgrade our store in the future we won't have to wory about the fact we have changed the "core" of the prestashop. All our changes will be kept in our theme directory away from the main install. Then create a file under this folder called NAME OF MODULE.tpl.


http://www.techietips.net/creating-prestashop-13-theme-part-3.html

Share this post


Link to post
Share on other sites

The mechanism I'm using would mean that to display the search block in the footer you would write:
{plugin module='blocksearch' hook='rightColumn'}



anywhere you want the block to display in (e.g. anywhere you care to place it in footer.tpl). No hooks, no changes to core files (except the overrides and additional class to support the functionality) and no manually coded modules - just edit the theme template and it's done.

If you wanted the search in both the header and footer, then you would capture the output as in the cart example above, and then display the variable in both template files. The only issue with doing that might be that there may be validation issues with the markup (id's used more than once for example).

Paul



This reminds me of a mod I did sometime ago:
http://www.prestashop.com/forums/viewthread/61808/third_party_modules/placing_modules_anywhere_in_the_tpl_files

Great minds think alike - I didn't consider playing with smarty plugins until 1.4 as I absolutely hate hacking the core code and assumed that this would be required to get it to work. I posted about calling module hooks directly on my blog a while back and then couldn't think of a practical way of using it now. Did you do it all via the module? I guess if you ran a module on a hook early enough they would be available from then on?

This started because I wanted to replace things like a custom greeting depending on the time of day, content from cms pages inserted conditionally etc. that had been done as little hacky modules before (by someone else on a broken site I inherited to fix); and smarty plugins seemed like a good way of doing it cleanly. The other main thing I'm using it for is displaying Prestashop variables - Again, why hard-code addresses, telephone numbers etc. that are already stored and editable from the back office? The only other way is to write yet another module to assign them to smarty, make sure it's installed, hook it appropriately etc. not very friendly for theme designers who don;t want to have tolearn how the internals of Prestashop works...

Paul

Share this post


Link to post
Share on other sites

I went and read the thread, yup - although you have to keep re-applying the changes in 1.3 which puts me off, since I'm never working on my own site and the next upgrade would break the customer's site lol

I'm looking at a method whereby you can just drop in new plugins to a directory and then they're available - or even have a directory in the theme to allow you to add such extensions, contained within the theme. The problem is that you need to register the smarty plugins BEFORE the theme starts getting rendered so there needs to be something external to enable the whole mechanism (a module may be able to do it I guess).

I'm currently working on having the guts of it as a class (Plugin), and then overriding the FrontController with:

class FrontController extends FrontControllerCore
{
 protected static $plugin;

 function __construct()
 {
   parent::__construct();
   self::$plugin = new Plugin();
 }

 function init()
 {
   parent::init();

   self::$plugin->init();
 }



Paul

Share this post


Link to post
Share on other sites

  • 2 months later...

To display the module's output. You would obviously unhook the module from it's default display location to prevent Prestashop trying to display it as a normal hooked module. Unfortunately the latest version, which supports smarty 3, is still in testing but it will be released soon with lots of other helpful goodies to make stunning 1.4 themes a breeze :)

Paul

Hi, Paul,

I always read you and Rocky with pleasure, just a question : when your smart theme plug-in will be OK with smarty3?
This is so great an idea. I know, this is tough.
Just waiting...

I sincerely commend you,

Joe

Share this post


Link to post
Share on other sites

  • 2 weeks later...

Now that 1.4.2 (actually 1.4.2.5) is out i was wondering if the solution of PaulC (using a plugin) will work with this new version and with smartyv3. The PS team is flying with new versions so it is hard to keep up, ergo we need soluytions like PaulC's to be able to upgrade without a hassle

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...

Important Information

Cookies ensure the smooth running of our services. Using these, you accept the use of cookies. Learn More