Jump to content

Surcharge fichiers d'un module


Recommended Posts

Bonjour,

Il existe un mécanisme (voir function display dans classes/Module.php en 1.3 et 1.4) pour surcharger les templates smarty d'un module : créer un sous-dossier modules/monmodule/ dans le thème actif et y placer les fichiers tpl modifiés.

Mais, mais, existe-t-il un mécanisme permettant de surcharger aussi les fichiers php d'un module ? En particulier, pour un module type bloc front-office, il s'agirait de surcharger les fonctions hook. Connaissez-vous un tel mécanisme ?

Merci !

Link to comment
Share on other sites

Juste pour rigoler, en 1.4.3, dans classes/Module.php, dans la fonction hookExec, en remplaçant la ligne :

$display = call_user_func(array($moduleInstance, 'hook'.$hook_name), $hookArgs);


par

// HACK - start 
// check if there is an override of this hook in the theme dir
$hookOverriden = false;
if (file_exists(_PS_THEME_DIR_.'modules/'.$array['module'].'/'.$array['module'].'.php'))
{
   // include the file
   include_once(_PS_THEME_DIR_.'modules/'.$array['module'].'/'.$array['module'].'.php');
   // the hack module class name
   $hackModuleName = $array['module'].'_hack';
   // is it a class ?
   if (class_exists($hackModuleName, false))
   {
       if (!isset(self::$_INSTANCE[$hackModuleName]))
           self::$_INSTANCE[$hackModuleName] = new $hackModuleName;
       $hackModuleInstance = self::$_INSTANCE[$hackModuleName];
       if (is_callable(array($hackModuleInstance, 'hook'.$hook_name)))
           $hookOverriden = true;
   }
}
if ($hookOverriden && isset($hackModuleInstance))
   $display = call_user_func(array($hackModuleInstance, 'hook'.$hook_name), $hookArgs);
else
   $display = call_user_func(array($moduleInstance, 'hook'.$hook_name), $hookArgs);
// HACK - end



On peut créer dans le dossier template/modules/monmodule un fichier monmodule.php avec une classe monmodule_hack qui ne contient que des surcharges des fonctions de hook et celles-ci seront prioritaires sur celles du module de base.

Si ça peut servir à quelqu'un.

Link to comment
Share on other sites

Je suis également intéressé pour savoir s'il est possible de surcharger les fichiers php des modules.
J'ai essayé de créer un dossier modules dans override mais cela ne fonctionne pas (on peut toujours essayer^^)
S'il existe une méthode j'aimerai bien la connaître histoire de coder proprement (quitte à surcharger les classes et les controllers autant le faire jusqu'au bout avec les modules etc.)

Link to comment
Share on other sites

En fait, après avoir analysé le code de Module.php (et tant d'autres classes / mécanismes !!), il existe la surcharge pour les fichiers tpl mais pas pour php. Ou alors elle est vraiment bien cachée !! D'où le petit hack (pas très propre, c vrai !).
Peut-être en 1.5 ? Je n'ai pas encore regardé.

Link to comment
Share on other sites

Merci pour l'info
Je regarderai également du côté de la 1.5 mais bon, dommage que ce ne soit pas déjà pris en compte dans la 1.4
En attendant, dans le doute, je conserve toujours une version par défaut de mes fichiers php ;)

Link to comment
Share on other sites

  • 2 months later...

Juste pour rigoler, en 1.4.3, dans classes/Module.php, dans la fonction hookExec, en remplaçant la ligne :

$display = call_user_func(array($moduleInstance, 'hook'.$hook_name), $hookArgs);

par

// HACK - start
// check if there is an override of this hook in the theme dir
$hookOverriden = false;
if (file_exists(_PS_THEME_DIR_.'modules/'.$array['module'].'/'.$array['module'].'.php'))
{
// include the file
include_once(_PS_THEME_DIR_.'modules/'.$array['module'].'/'.$array['module'].'.php');
// the hack module class name
$hackModuleName = $array['module'].'_hack';
// is it a class ?
if (class_exists($hackModuleName, false))
{
	if (!isset(self::$_INSTANCE[$hackModuleName]))
		self::$_INSTANCE[$hackModuleName] = new $hackModuleName;
	$hackModuleInstance = self::$_INSTANCE[$hackModuleName];
	if (is_callable(array($hackModuleInstance, 'hook'.$hook_name)))
		$hookOverriden = true;
}
}
if ($hookOverriden && isset($hackModuleInstance))
$display = call_user_func(array($hackModuleInstance, 'hook'.$hook_name), $hookArgs);
else
$display = call_user_func(array($moduleInstance, 'hook'.$hook_name), $hookArgs);
// HACK - end

On peut créer dans le dossier template/modules/monmodule un fichier monmodule.php avec une classe monmodule_hack qui ne contient que des surcharges des fonctions de hook et celles-ci seront prioritaires sur celles du module de base.

Si ça peut servir à quelqu'un.

Bonjour,

 

J’essaye d'appliquer votre hack.

 

Je l'ai donc mis dans la classe Module dans /override/classes/ et Module.php commence avec ceci :

class Module extends ModuleCore {

J'ai repris tout le contenu de la classe d'origine Module en modiffiant hookExec avec ton Hack.

J'ai bien mis la classe php du module dans le dossier /themes/montheme/modules/blockmyaccount/blockmyaccount.php

 

dedans j'ai

class BlockMyAccount_hack extends Module
{

public function hookLeftColumn($params)
{
 global $smarty;

 if (!$params['cookie']->isLogged())
  return false;
 $smarty->assign(array(
  'voucherAllowed' => (int)(Configuration::get('PS_VOUCHERS')),
  'returnAllowed' => (int)(Configuration::get('PS_ORDER_RETURN')),
  'HOOK_BLOCK_MY_ACCOUNT' => Module::hookExec('myAccountBlock')
 ));
 return $this->display(__FILE__, $this->name.'.tpl');
}

public function hookFooter($params)
{
 return $this->hookLeftColumn($params);
}
}

 

Malheuresement cela ne fonctionne pas.

 

Où j'ai oublié quelque chose ?

 

Merci.

Link to comment
Share on other sites

Bonjour,

 

Je l'ai donc mis dans la classe Module dans /override/classes/ et Module.php commence avec ceci :

class Module extends ModuleCore {

J'ai repris tout le contenu de la classe d'origine Module en modiffiant hookExec avec ton Hack.

 

Je n'ai pas essayé en surchargeant la classe Module, mais en modifiant directement la classe dans le core (c'était juste pour essayer !). En théorie, ça doit fonctionner.

 

Je teste dès que je peux pour te dire ce qu'il en est. Attention, je n'ai testé qu'en 1.4.3. Quelle ta version ?

Link to comment
Share on other sites

Alors, j'ai testé avec la 1.4.4.1 et ça fonctionne très bien chez moi (sur Windows). Voilà le topo complet :

 

- ne touche pas à la classe Module du core (dossier classes/)

- renomme la classe _Module.php en Module.php présente dans le dossier override/classes

- dans cette classe, copie la fonction hookExec() de la classe ModuleCore

- modifie cette fonction comme indiqué dans le hack

- dans le theme actif, crée dossier modules/blockmyaccount

- copie dans ce dossier un fichier blockmyaccount.php vierge dans lequel on copie le code que tu as indiqué ci-dessus. La classe doit effectivement s'appeler BlockMyAccount_hack

- pour être fixé plus vite, j'ai modifié ton code de hook pour y indiquer simplement

echo 'HACK SUCCESS<br />';
die();

 

Avec ça, pas de pb, ça marche.

Essaye et dis-moi ce qu'il en est.

Link to comment
Share on other sites

Bonjour,

 

Merci cela fonctionne bien effectivement.

 

Par contre il ne charge pas le tpl. J'ai découvert que la référence $this->name était vide dans

return $this->display(__FILE__, $this->name.'.tpl');

J'ai le code suivant maintenant

return $this->display(__FILE__, 'blockmyaccount.tpl');

 

Merci beaucoup.

 

Ton hack va bien m'aider

Link to comment
Share on other sites

  • 2 months later...

J'ai plutôt adopté pour la modification de la méthode getInstanceByName qui, en prime, fonctionne également avec les modules de paiement !


class Module extends ModuleCore
{
.
.
.

public static function getInstanceByName($moduleName)
{
 if (!Tools::file_exists_cache(_PS_MODULE_DIR_.$moduleName.'/'.$moduleName.'.php'))
  return false;
/*** HACK START */
 if (file_exists(_PS_THEME_DIR_.'modules/'.$moduleName.'/'.$moduleName.'.php'))
 {
  // include the file
  include_once(_PS_THEME_DIR_.'modules/'.$moduleName.'/'.$moduleName.'.php');// <- NEW ALTERNATIVE
  $moduleName = $moduleName.'_ovr';
 }else{
  include_once(_PS_MODULE_DIR_.$moduleName.'/'.$moduleName.'.php'); // <- ORIGINAL LINE
 }
/*** HACK END */
 if (!class_exists($moduleName, false))
  return false;
 if (!isset(self::$_INSTANCE[$moduleName]))
  self::$_INSTANCE[$moduleName] = new $moduleName;
 return self::$_INSTANCE[$moduleName];
}

La modification est également plus simple à mettre en oeuvre puisque je me contente de remplacer 1 seule ligne par un test !

 

Bien entendu, ce fichier de classe est à placer dans le dossier /override/classes

Link to comment
Share on other sites

  • 2 months later...

J'ai plutôt adopté pour la modification de la méthode getInstanceByName qui, en prime, fonctionne également avec les modules de paiement !


class Module extends ModuleCore
{
.
.
.

public static function getInstanceByName($moduleName)
{
 if (!Tools::file_exists_cache(_PS_MODULE_DIR_.$moduleName.'/'.$moduleName.'.php'))
  return false;
/*** HACK START */
 if (file_exists(_PS_THEME_DIR_.'modules/'.$moduleName.'/'.$moduleName.'.php'))
 {
  // include the file
  include_once(_PS_THEME_DIR_.'modules/'.$moduleName.'/'.$moduleName.'.php');// <- NEW ALTERNATIVE
  $moduleName = $moduleName.'_ovr';
 }else{
  include_once(_PS_MODULE_DIR_.$moduleName.'/'.$moduleName.'.php'); // <- ORIGINAL LINE
 }
/*** HACK END */
 if (!class_exists($moduleName, false))
  return false;
 if (!isset(self::$_INSTANCE[$moduleName]))
  self::$_INSTANCE[$moduleName] = new $moduleName;
 return self::$_INSTANCE[$moduleName];
}

La modification est également plus simple à mettre en oeuvre puisque je me contente de remplacer 1 seule ligne par un test !

 

Bien entendu, ce fichier de classe est à placer dans le dossier /override/classes

 

Ne serait-il pas plus correct de placer les surcharges des fichiers php du module dans le dossier override/modules/module_name/file_overrided.php ? Le dossier du theme ne devrait pas contenir de code me semble-t-il ?

 

Sinon, quelqu'un a-t-il regardé si un tel mécanisme est prévu pour la 1.5 ou si l'on meilleur temps d'adopter le hack à plus ou moins long terme ? :-)

  • Like 1
Link to comment
Share on other sites

Thanks for a great idea to overwrite module php file.

I extended your code to support the solution for overwitting the module php file and extend the base class of module.

This solution provides an advantage to NOT copy all the code from base module but to make overwites only to the functions needed like original prestashop overwite solution.

 

 

Create a file Module.php in the override/classes/

class Module extends ModuleCore{
public static function getInstanceByName($moduleName)
{
 if (!isset(self::$_INSTANCE[$moduleName]))
 {
  if (Tools::file_exists_cache(_PS_MODULE_DIR_.$moduleName.'/'.$moduleName.'.php'))
  {
include_once(_PS_MODULE_DIR_.$moduleName.'/'.$moduleName.'.php');  

/*** HACK START */
if (file_exists(_PS_THEME_DIR_.'modules/'.$moduleName.'/'.$moduleName.'.php')){
 // include the file
 include_once(_PS_THEME_DIR_.'modules/'.$moduleName.'/'.$moduleName.'.php');// <- NEW ALTERNATIVE
 $moduleName = $moduleName.'Ovr';
}
/*** HACK END */
if(class_exists($moduleName, false)){
 return self::$_INSTANCE[$moduleName] = new $moduleName;
}
  }
  return false;
 }
 return self::$_INSTANCE[$moduleName];
}
}

 

Then create a module overwite in the theme/modules/mymodule/ and make overwrites

class MyModuleOvr extends MyModule{
public function example($params)
{
 .....
}
}

Link to comment
Share on other sites

Bonjour, j'ai mis en place la méthode de Niofox pour surcharger la méthode hookNewOrder du module mailalert car j'aimerais intégrer le total de poids des produits de la commande dans le mail envoyé aux administrateurs mais ça ne fonctionne pas.

L'ajout de code que j'ai fait fonctionne par contre bien si je ne surcharge pas la méthode et que je modifie directement la class au niveau du plugin.

 

Voilà mon code si quelqu'un remarque quelquechoses :

 

La class module contenant la surcharge de la méthode getInstanceByName() de l'objet Module :

 

class Module extends ModuleCore{
public static function getInstanceByName($moduleName)
{
 if (!isset(self::$_INSTANCE[$moduleName]))
 {
  if (Tools::file_exists_cache(_PS_MODULE_DIR_.$moduleName.'/'.$moduleName.'.php'))
  {
include_once(_PS_MODULE_DIR_.$moduleName.'/'.$moduleName.'.php');
/*** HACK START */
if (file_exists(_PS_THEME_DIR_.'modules/'.$moduleName.'/'.$moduleName.'.php')){
 // include the file
 include_once(_PS_THEME_DIR_.'modules/'.$moduleName.'/'.$moduleName.'.php');// <- NEW ALTERNATIVE
 $moduleName = $moduleName.'Ovr';
}
  /*** HACK END */
if(class_exists($moduleName, false)){
 return self::$_INSTANCE[$moduleName] = new $moduleName;
}
  }
  return false;
 }
 return self::$_INSTANCE[$moduleName];
}
}

 

voilà ce que j'ai ajouté dans le répertoire module/mailalert de mont thème :

 

if (!defined('_CAN_LOAD_FILES_'))
exit;

class MailAlertsOvr extends MailAlerts
{
public function hookNewOrder($params)
{
	if (!$this->_merchant_order OR empty($this->_merchant_mails))
		return;

	// Getting differents vars
	$id_lang = (int)Configuration::get('PS_LANG_DEFAULT');
	 $currency = $params['currency'];
	$configuration = Configuration::getMultiple(array('PS_SHOP_EMAIL', 'PS_MAIL_METHOD', 'PS_MAIL_SERVER', 'PS_MAIL_USER', 'PS_MAIL_PASSWD', 'PS_SHOP_NAME'));
	$order = $params['order'];
	$customer = $params['customer'];
	$delivery = new Address((int)($order->id_address_delivery));
	$invoice = new Address((int)($order->id_address_invoice));
	$order_date_text = Tools::displayDate($order->date_add, (int)($id_lang));
	$carrier = new Carrier((int)($order->id_carrier));
	$message = $order->getFirstMessage();
	if (!$message OR empty($message))
		$message = $this->l('No message');

	$itemsTable = '';

	$products = $params['order']->getProducts();
	$customizedDatas = Product::getAllCustomizedDatas(intval($params['cart']->id));
	Product::addCustomizationPrice($products, $customizedDatas);
	foreach ($products AS $key => $product)
	{
		$unit_price = $product['product_price_wt'];
		$price = $product['total_price'];

		$customizationText = '';
		if (isset($customizedDatas[$product['product_id']][$product['product_attribute_id']]))
		{

			foreach ($customizedDatas[$product['product_id']][$product['product_attribute_id']] AS $customization)
			{
				if (isset($customization['datas'][_CUSTOMIZE_TEXTFIELD_]))
					foreach ($customization['datas'][_CUSTOMIZE_TEXTFIELD_] AS $text)
						$customizationText .= $text['name'].':'.' '.$text['value'].'
';

				if (isset($customization['datas'][_CUSTOMIZE_FILE_]))
					$customizationText .= sizeof($customization['datas'][_CUSTOMIZE_FILE_]) .' '. Tools::displayError('image(s)').'
';

				$customizationText .= '---
';
			}

			$customizationText = rtrim($customizationText, '---
');
		}

		$itemsTable .=
			'
				'.$product['product_reference'].'
				[b]'.$product['product_name'].(isset($product['attributes_small']) ? ' '.$product['attributes_small'] : '').(!empty($customizationText) ? '
'.$customizationText : '').'[/b]
				'.Tools::displayPrice($unit_price, $currency, false).'
				'.(int)($product['product_quantity']).'
				'.Tools::displayPrice(($unit_price * $product['product_quantity']), $currency, false).'
			';
	}
	foreach ($params['order']->getDiscounts() AS $discount)
	{
		$itemsTable .=
		'
				'.$this->l('Voucher code:').' '.$discount['name'].'
				-'.Tools::displayPrice($discount['value'], $currency, false).'
		';
	}
	if ($delivery->id_state)
		$delivery_state = new State((int)($delivery->id_state));
	if ($invoice->id_state)
		$invoice_state = new State((int)($invoice->id_state));

	// Filling-in vars for email
	$template = 'new_order';
	$subject = $this->l('New order', $id_lang);
	$templateVars = array(
		'{firstname}' => $customer->firstname,
		'{lastname}' => $customer->lastname,
		'{email}' => $customer->email,
		'{delivery_block_txt}' => $this->_getFormatedAddress($delivery, "\n"),
		'{invoice_block_txt}' => $this->_getFormatedAddress($invoice, "\n"),
		'{delivery_block_html}' => $this->_getFormatedAddress($delivery, "
",
					array(
						'firstname'	=> '[color=#DB3484][b]%s[/b][/color]',
						'lastname'	=> '[color=#DB3484][b]%s[/b][/color]')),
		'{invoice_block_html}' => $this->_getFormatedAddress($invoice, "
",
					array(
						'firstname'	=> '[color=#DB3484][b]%s[/b][/color]',
						'lastname'	=> '[color=#DB3484][b]%s[/b][/color]')),
		'{delivery_company}' => $delivery->company,
		'{delivery_firstname}' => $delivery->firstname,
		'{delivery_lastname}' => $delivery->lastname,
		'{delivery_address1}' => $delivery->address1,
		'{delivery_address2}' => $delivery->address2,
		'{delivery_city}' => $delivery->city,
		'{delivery_postal_code}' => $delivery->postcode,
		'{delivery_country}' => $delivery->country,
		'{delivery_state}' => $delivery->id_state ? $delivery_state->name : '',
		'{delivery_phone}' => $delivery->phone,
		'{delivery_other}' => $delivery->other,
		'{invoice_company}' => $invoice->company,
		'{invoice_firstname}' => $invoice->firstname,
		'{invoice_lastname}' => $invoice->lastname,
		'{invoice_address2}' => $invoice->address2,
		'{invoice_address1}' => $invoice->address1,
		'{invoice_city}' => $invoice->city,
		'{invoice_postal_code}' => $invoice->postcode,
		'{invoice_country}' => $invoice->country,
		'{invoice_state}' => $invoice->id_state ? $invoice_state->name : '',
		'{invoice_phone}' => $invoice->phone,
		'{invoice_other}' => $invoice->other,
		'{order_name}' => sprintf("%06d", $order->id),
		'{shop_name}' => Configuration::get('PS_SHOP_NAME'),
		'{date}' => $order_date_text,
		'{carrier}' => (($carrier->name == '0') ? Configuration::get('PS_SHOP_NAME') : $carrier->name),
		'{payment}' => Tools::substr($order->payment, 0, 32),
		'{items}' => $itemsTable,
		'{total_paid}' => Tools::displayPrice($order->total_paid, $currency),
		'{total_products}' => Tools::displayPrice($order->getTotalProductsWithTaxes(), $currency),
		'{total_discounts}' => Tools::displayPrice($order->total_discounts, $currency),
		'{total_shipping}' => Tools::displayPrice($order->total_shipping, $currency),
		'{total_wrapping}' => Tools::displayPrice($order->total_wrapping, $currency),
		'{total_weight}' => Tools::ps_round($order->getTotalWeight(), 2),
		'{currency}' => $currency->sign,
		'{message}' => $message
	);
	$iso = Language::getIsoById((int)($id_lang));
	if (file_exists(dirname(__FILE__).'/mails/'.$iso.'/'.$template.'.txt') AND file_exists(dirname(__FILE__).'/mails/'.$iso.'/'.$template.'.html'))
		Mail::Send($id_lang, $template, $subject, $templateVars, explode(self::__MA_MAIL_DELIMITOR__, $this->_merchant_mails), NULL, $configuration['PS_SHOP_EMAIL'], $configuration['PS_SHOP_NAME'], NULL, NULL, dirname(__FILE__).'/mails/');
}
}

 

sachant que j'ai aussi dans mon répertoire module/mailalert le répertoire mails avec l'ajout de la valeur {total_wieght}.

 

Voilà, tout ce que je peux dire c'est que comme ça ne fonctionne pas et que du coup j'ai du le faire en direct dans mon module et je n'aime pas ça !!!

Link to comment
Share on other sites

  • 2 weeks later...

En partant du post de globule, j'ai un peu modifié comme ceci (je suis en v1.4.7.0) :

 

class Module extends ModuleCore
{
public static function getInstanceByName($moduleName)
{
 if (!isset(self::$_INSTANCE[$moduleName]))
 {
  if (Tools::file_exists_cache(_PS_MODULE_DIR_.$moduleName.'/'.$moduleName.'.php'))
  {
include_once(_PS_MODULE_DIR_.$moduleName.'/'.$moduleName.'.php');

/*** HACK START */
if (file_exists(_PS_THEME_DIR_.'modules/'.$moduleName.'/'.$moduleName.'.php')) {
 // include the file
 include_once(_PS_THEME_DIR_.'modules/'.$moduleName.'/'.$moduleName.'.php');// <- NEW ALTERNATIVE
 $moduleName = $moduleName.'_ovr';
}
/*** HACK END */

if (class_exists($moduleName, false))
 return self::$_INSTANCE[$moduleName] = new $moduleName;
  }
  return false;
 }
 return self::$_INSTANCE[$moduleName];			
}
}

 

Ce qui me permet de surcharger mon module , en créant le fichier :

 

themes/montheme/modules/monmodule/monmodule.php

 

Que j'écris ensuite de la façon suivante :

 

<?php
class MonModule_ovr extends MonModule
{
public function hookHome($params)
{
 return 'It Works .... GREAT !';
}
}

 

Ce qui me permet de ne pas avoir à copier coller tout le contenu du module, mais juste surcharger les méthodes qui m'intéressent !!

Merci au posts précédents qui m'ont aidé à faire ça , en espérant que ça vous aide aussi !!

Link to comment
Share on other sites

Bonsoir messieurs,

 

(bien que cassant le M.V.C. initial de la solution)

 

Je l'ai mis à la norme, c'est une très bonne idée.

 

Par ailleurs, j'ai suffixé les classes modules étendues par "Theme", de façon à garder la cohérence.

  • BlockTags => BlockTagsTheme
  • BlockCategories => BlockCategoriesTheme
  • Etc => EtcTheme (humour)

 

Cadeau : https://gist.github.com/2287709

Link to comment
Share on other sites

Super !!

 

Pour info, je trouve l'override être une très bonne idée de l'équipe prestashop, car avant cela les mises à jour de version pouvait être périlleuses si on avait modifié le coeur de l'appli avant. Mais pour ma part, ce sont les modules que je modifie le plus souvent, car un hook donc j'ai besoin n'est pas implémenté, ou les quantité de produits retournés par le module sont codés en dur, etc ... ce qui fait que l'override ne m'a pas souvent été d'une très grande utilité, mais là ça commence à devenir intéressant !!

 

merci.

Link to comment
Share on other sites

Bonsoir messieurs,

 

(bien que cassant le M.V.C. initial de la solution)

 

Je l'ai mis à la norme, c'est une très bonne idée.

 

Par ailleurs, j'ai suffixé les classes modules étendues par "Theme", de façon à garder la cohérence.

  • BlockTags => BlockTagsTheme
  • BlockCategories => BlockCategoriesTheme
  • Etc => EtcTheme (humour)

Cadeau : https://gist.github.com/2287709

 

Bien le bonjour !

 

 

Pourquoi ne pas remplacer

 

_PS_THEME_DIR_.'modules/'.$module_name.'/'.$module_name.'.php'

 

par

 

_PS_BASE_URI_ . '/override/modules/'.$module_name.'/'.$module_name.'.php'

 

 

Accessoirement, on pourrait créer la constante _PS_OVERRIDE_DIR_ valant _PS_BASE_URI_ . 'override/' puisqu'on y est et ainsi faire

 

 

_PS_OVERRIDE_DIR_ . 'modules/'.$module_name.'/'.$module_name.'.php'

 

 

 

Ceci aurait l'avantage de sortir le code du dossier theme et on respecterait autant le modèle MVC qu'avec le reste des overrides ...

De plus, on pourrait retirer ce "Theme" ajouté au nom du module par votre code, celui-ci n'ayant plus lieu d'être.

 

Enfin, c'est une idée comme une autre.

  • Like 1
Link to comment
Share on other sites

  • 1 month later...

Bonsoir messieurs,

 

(bien que cassant le M.V.C. initial de la solution)

 

Je l'ai mis à la norme, c'est une très bonne idée.

 

Par ailleurs, j'ai suffixé les classes modules étendues par "Theme", de façon à garder la cohérence.

  • BlockTags => BlockTagsTheme
  • BlockCategories => BlockCategoriesTheme
  • Etc => EtcTheme (humour)

Cadeau : https://gist.github.com/2287709

 

Petite remarque sur le débat de l'emplacement du dossier d'override des modules :

 

J'ai pris le parti de les mettre dans le thème car il comporte déjà des override des fichiers tpl et définir un second emplacement (override/modules) embrouille quelque peu les idées ...

De plus, cette solution présente l'avantage de permettre aux développeurs de thèmes de fournir la réécriture complète des modules au sein même de leurs thèmes !

L'inconvénient est que si vous changez de thème dans l'admin vous perdez les overrides de modules du thème ... mais qui change de thème régulièrement ?

 

L'idée de Julien prend alors tout sont sens en remplaçant l'extrension "_ovr" par l'extension "Theme" !

 

Petit complément

J'ai utilisé cette méthode pour modifier le blockCart mais j'ai rencontré un problème avec les JS !

Voici ma solution :

 

public function __construct($name = NULL)
{
if ($this->name == NULL)
$this->name = $this->id;
if ($this->name != NULL)
{
if (self::$modulesCache == NULL AND !is_array(self::$modulesCache))
{
self::$modulesCache = array();
$result = Db::getInstance()->ExecuteS('SELECT * FROM `'.pSQL(_DB_PREFIX_.$this->table).'`');
foreach ($result as $row)
self::$modulesCache[$row['name']] = $row;
}
if (isset(self::$modulesCache[$this->name]))
{
$this->active = true;
$this->id = self::$modulesCache[$this->name]['id_module'];
foreach (self::$modulesCache[$this->name] AS $key => $value)
if (key_exists($key, $this))
$this->{$key} = $value;
/*ORIGINAL
*  $this->_path = __PS_BASE_URI__.'modules/'.$this->name.'/';
* */

/*** HACK START */
if (file_exists(_PS_THEME_DIR_.'modules/'.$this->name.'/'.$this->name.'.php'))
{
$this->_path = __PS_BASE_URI__.'themes/'._THEME_NAME_.'/modules/'.$this->name.'/';
}else{
$this->_path = __PS_BASE_URI__.'modules/'.$this->name.'/';
}
/*** HACK END */
}
}
}

Merci de l'ajouter sur Github ... ;)

Edited by globule (see edit history)
Link to comment
Share on other sites

  • 4 months later...

Hi everybody,

 

I ve work with prestashop V1.4.3 from last year and I m switching to V1.5 and as long as I understand what Julien Breux say about the right position for overriding the php file of module I still prefer to override them in the override folder. For maintenance reason I still allow the official way to override, wich permit me to develop as I want, in the same time I m able to download official modules.

 

What about the V1.5 and the multisite system ?

 

here what I use :

 

 

/*********************************************************

* Override of Module Core *

* Use this override to override (^^) module classes *

* *

* source : https://gist.github.com/2287709 *

* FILES INVOLVED : *

* - root/override/classes/Module.php *

* *

* @version 1.0.0 *

* @author Julien BREUX <[email protected]> *

* *

* Return an instance of the specified module *

* *

* @param string $module_name Module name *

* @return Module *

* */

public static function getInstanceByName($module_name) {

if (!isset(self::$_INSTANCE[$module_name]))

{

if (Tools::file_exists_cache(_PS_MODULE_DIR_.$module_name.'/'.$module_name.'.php'))

{

include_once(_PS_MODULE_DIR_.$module_name.'/'.$module_name.'.php');

 

$override_module_file = _PS_ROOT_DIR_.'/override/modules/'.$module_name.'/'.$module_name.'.php';

$override_theme_module_file = _PS_THEME_DIR_.'modules/'.$module_name.'/'.$module_name.'.php';

 

if (file_exists($override_module_file))

{

require_once $override_module_file;

$module_name .= '_Overrided';

} elseif (file_exists($override_theme_module_file)) {

require_once $override_theme_module_file;

$module_name .= 'Theme';

}

 

if (class_exists($module_name, false))

return self::$_INSTANCE[$module_name] = new $module_name;

}

return false;

}

return self::$_INSTANCE[$module_name];

} // END METHOD

/* *

* /Override of Module Core *

*********************************************************/

  • Like 1
Link to comment
Share on other sites

  • 3 months later...

Bonjour,

 

J'ai la version 1.5.3.1 qui contient une méthode installOverrides() dans Module.php. Cela ne semble pas fonctionner des masses par contre. Quelqu'un a déjà utilisé ce système?

 

qu'est ce qui te fait dire que ça ne fonctionne pas des masses ?

Link to comment
Share on other sites

J'essaie de surcharger le fichier \modules\blockpaymentlogo\blockpaymentlogo.php. La méthode installOverrides, d'après ce que je comprend regarde le contenu d'un répertoire "override" situé sous \modules\blockpaymentlogo (là je trouve pas ça très logique par rapport aux autres type de surchage):

 

$this->getLocalPath().'override'

 

Je mets donc mon fichier de surcharge: blockpaymentlogo.php dans ce folder.

Pour info, le contenu est:

 

if (!defined('_PS_VERSION_'))
exit;
class BlockPaymentLogo extends Module
{
 public function install()
  {
   if (!$this->registerHook('footer'))
 return false;
   return true;
  }
 public function hookFooter($params)
 {
  $this->smarty->assign('cms_payement_logo_test', 'test');
  return true;
 }
}

 

Je désintalle et ré-installe le module. Pas de différence. Le contenu du hook footer est celui défini dans le fichier d'origine.

 

J'ai peut-être raté un point ... une idée?

 

Y'a aussi la partie ci-dessous de cette méthode que je ne comprends pas:

 

Autoload::getInstance()->getClassPath($class.'Core')

Link to comment
Share on other sites

Sans vouloir trop m'avancer, il me semble que ces overrides dont tu parles, dans module/monmodule/override/ ne servent qu'à surcharger les classes, controllers frontend/backend. Je n'ai cependant pas tester de surcharger une classe de module ainsi, mais je vois mal, au vu du code de l'autoloader et du code d'installOverrides, comment cela serait possible ...

 

Quant à la partie citée,

Autoload::getInstance()->getClassPath($class.'Core')

 

Je ne vois pas en quoi tu ne la comprends pas ? :-) Elle sert à vérifier si la class que tu tentes de surcharger existe dans les classes "surchargeable" (étant donc du Core).

Edited by mdiblasio (see edit history)
Link to comment
Share on other sites

Effectivement, ce serait vraiment nécessaire, tout comme la surcharge multiple d'une classe. Si un module surcharge la classe Product, actuellement, aucun autre ne peut le faire à moins "d'annuler" la première surcharge.

 

C'est un peu dommage, j'ai fais une suggestion à ce sujet sur la forge, peut-être en faudrait-il également une pour la surcharge de module, j'avoue ne pas avoir cherché !

Link to comment
Share on other sites

Effectivement, ce serait vraiment nécessaire, tout comme la surcharge multiple d'une classe. Si un module surcharge la classe Product, actuellement, aucun autre ne peut le faire à moins "d'annuler" la première surcharge.

 

il est parfaitement possible d'avoir plusieurs override d'une même classe dans la mesure ou les fonctions sont différentes.

Link to comment
Share on other sites

@coeos.pro : Effectivement, je le vois maintenant en relisant le code de addOverride. J'avais testé avant le "bug fix" du 26 octobre. Super nouvelle ! Je vais pouvoir corriger certains de mes overrides pour être "plus propre" ! Merci !

 

Pour les surcharges de la même méthode, j'avoue avoir "bricoler" pour le moment, héritant des classes crée par mes autres modules avant de faire hériter Product, par exemple, de la dernière de mes classes (les méthodes "Identique" appelant la méthode parent, on perd rien).

 

Je vais voir pour faire cohabiter les deux systèmes :) Merci pour ta petite phrase d'info qui m'aura bien changé la vie ! ;-)

Link to comment
Share on other sites

  • 2 years later...

Bonsoir messieurs,

 

(bien que cassant le M.V.C. initial de la solution)

 

Je l'ai mis à la norme, c'est une très bonne idée.

 

Par ailleurs, j'ai suffixé les classes modules étendues par "Theme", de façon à garder la cohérence.

  • BlockTags => BlockTagsTheme
  • BlockCategories => BlockCategoriesTheme
  • Etc => EtcTheme (humour)

Cadeau : https://gist.github.com/2287709

 

 

Bonjour,

 

Navré de poser la question dans ce vieux post.. mais je n'ai pas l'impression que cela soit intégré de base dans la 1.6 après avoir lu la documentation à ce sujet.

Je rencontre le même problème et je voudrais appliquer la meilleure méthode. Pourriez-vous me renseigner svp ?

Si c'est intégré dans la 1.6, comment faire ? Si non, je vais utiliser le hack décrit dans ce post.

 

Merci !

Link to comment
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
×
×
  • Create New...