1.4 Plugins Revisited - Part 1

Plugins Evolved

A while ago when I wrote the original article on Prestashop plugins I promised a follow-up to allow it to be used with smarty 3. Unfortunately work has kept me from a proper write-up so I'm only now getting around to publishing the next version. I had intended adding the ability to easily extend the functionality on a per-theme basis, but since the demand for some usable code right now has been so great I've decided to publish this in two parts.

The new Plugin class

When I originally started work on this I had in mind that it may be useful for people to be able to override the plugin class using the same method Prestashop uses for its own core classes. While implementing it in a real-world Prestashop site however, I decided that this wasn't such a good idea and the Plugin class is now implemented as a simple additional class. In Part 2 I'll detail the mechanism I've decided to implement in preference to the override system to allow others to extend the functionality of this.

**Note:* If you implemented the original PluginCore class from the >previous article, then you should delete the old Plugin.php class definition from the /classes drectory in your Prestashop installation.*

The new version of Plugin.php should now be placed in the /overrides/classes folder on your server:

class Plugin
{
  public static $initialized = false;
  protected static $smarty;
  protected static $cookie;
  protected static $link;
  protected static $cart;

  function init()
  {
    global $smarty, $cookie, $link, $cart;
    if (self::$initialized)
      return;
    self::$initialized = true;
    self::$cookie = $cookie;
    self::$cart = $cart;
    self::$smarty = $smarty;
    self::$link = $link;
    if (!Configuration::get('PS_FORCE_SMARTY_2'))
    {
      self::$smarty->registerPlugin('function', 'plugin', array('Plugin', 'ecs_smartyplugin'));
      self::$smarty->registerPlugin('function', 'cmspage', array('Plugin', 'ecs_smartycmspage'));
      self::$smarty->registerPlugin('function', 'psconfig', array('Plugin', 'ecs_smartypsconfig'));
    } else {
      self::$smarty->register_function('plugin', array('Plugin', 'ecs_smartyplugin'));
      self::$smarty->register_function('cmspage', array('Plugin', 'ecs_smartycmspage'));
      self::$smarty->register_function('psconfig', array('Plugin', 'ecs_smartypsconfig'));
    }
  }

  public static function moduleoutput($module, $hook, $hookArgs = array())
  {
    $output = '';
    if (!isset($hookArgs['cookie']) OR !$hookArgs['cookie'])
      $hookArgs['cookie'] = self::$cookie;
    if (!isset($hookArgs['cart']) OR !$hookArgs['cart'])
      $hookArgs['cart'] = self::$cart;
    $hookArgs['altern'] = 1;
    $instance = Module::getInstanceByName($module);
    if (is_callable(array($instance, 'hook'.$hook)))
      $output = call_user_func(array($instance,'hook'.$hook), $hookArgs);
    echo $output;
  }

  public static function cmspage($id_cms = 1)
  {
    $output = '';
    $cms = new CMS($id_cms, intval(self::$cookie->id_lang));
    if (Validate::isLoadedObject($cms))
      $output = $cms->content;
    return $output;
  }

  static function ecs_smartyplugin($params, &$smarty)
  {
    return Plugin::moduleoutput($params['module'], $params['hook'], isset($params['args']) ? $params['args'] : array());
  }

  static function ecs_smartycmspage($params, &$smarty)
  {
    return Plugin::cmspage($params['id']);
  }

  static function ecs_smartypsconfig($params, &$smarty)
  {
    return Configuration::get($params['item']);
  }
}

The main architectural difference apart from no longer declaring the class as a "Core" one is that all of the required code, including callbacks, is now contained within the class. This allows us to eliminate the global functions from within the FrontController class override. You will also notice that I have added another two basic elements to the class and now supports the following theme extensions by default:

  1. The original "plugin" code to insert module output from a specific hook. php {plugin module='homefeatured' hook='home'}
  2. A "cms" code which allows the output of a specific Prestashop CMS "page". This allows you to create "user-editable" areas in the theme that can be modified via the admin panel simply by changing the corresponding CMS document. By setting the documents to "disabled" they will also never show on the site other than where you need them to (if required). php {cmspage id='1'}
  3. A "psconfig" code to output the value of a Prestashop config variable. This is extremely handy when creating areas such as footers where you may wish to place information like the store address, telephone number etc. By using this mechanism the theme will always track the values set from the admin screens. php {psconfig item='PS_SHOP_PHONE'}

The FrontController override

Since we have moved the bulk of the code to the Plugin class now, we can simply use the following in /overrides/classes/FrontController.php:

class FrontController extends FrontControllerCore
{
  protected static $plugin;

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

  function init()
  {
    parent::init();
    self::$plugin->init();
  }
}

Download the required files

Once again, please regard these files as experimental. They are not guaranteed in any way and *could** cause your store to function incorrectly.*

Download Prestashop 1.4 Theme Plugin Extension v1.1.0

Continue to Part 2