Jump to content

[Documentation] Add & Remove Override au sein d'un module


Recommended Posts

Dans la version 1.5 de PrestaShop, il est possible d'ajouter un dossier "override" au module permettant, si besoin en est, d'installer un override via l'ajout du module.

 

Il existe deux méthodes: addOverride et removeOverride.

 

/**
 * Add all methods in a module override to the override class
 *
 * @param string $classname
 * @return bool
 */
public function addOverride($classname)
{
 $path = Autoload::getInstance()->getClassPath($classname.'Core');
 // Check if there is already an override file, if not, we just need to copy the file
 if (!($classpath = Autoload::getInstance()->getClassPath($classname)))
 {
  $override_src = $this->getLocalPath().'override'.DIRECTORY_SEPARATOR.$path;
  $override_dest = _PS_ROOT_DIR_.DIRECTORY_SEPARATOR.'override'.DIRECTORY_SEPARATOR.$path;
  if (!is_writable(dirname($override_dest)))
   throw new Exception(sprintf(Tools::displayError('directory (%s) not writable'), dirname($override_dest)));
  copy($override_src, $override_dest);
  return true;
 }

 // Check if override file is writable
 $override_path = _PS_ROOT_DIR_.'/'.Autoload::getInstance()->getClassPath($classname);
 if (!is_writable($override_path))
  throw new Exception(sprintf(Tools::displayError('file (%s) not writable'), $override_path));

 // Make a reflection of the override class and the module override class
 $override_file = file($override_path);
 eval(preg_replace(array('#^\s*<\?php#', '#class\s+'.$classname.'\s+extends\s+([a-z0-9_]+)(\s+implements\s+([a-z0-9_]+))?#i'), array('', 'class '.$classname.'OverrideOriginal'), implode('', $override_file)));
 $override_class = new ReflectionClass($classname.'OverrideOriginal');
 $module_file = file($this->getLocalPath().'override'.DIRECTORY_SEPARATOR.$path);
 eval(preg_replace(array('#^\s*<\?php#', '#class\s+'.$classname.'(\s+extends\s+([a-z0-9_]+)(\s+implements\s+([a-z0-9_]+))?)?#i'), array('', 'class '.$classname.'Override'), implode('', $module_file)));
 $module_class = new ReflectionClass($classname.'Override');
 // Check if none of the methods already exists in the override class
 foreach ($module_class->getMethods() as $method)
  if ($override_class->hasMethod($method->getName()))
   throw new Exception(sprintf(Tools::displayError('The method %1$s in the class %2$s is already overriden.'), $method->getName(), $classname));
 // Check if none of the properties already exists in the override class
 foreach ($module_class->getProperties() as $property)
  if ($override_class->hasProperty($property->getName()))
   throw new Exception(sprintf(Tools::displayError('The property %1$s in the class %2$s is already defined.'), $property->getName(), $classname));
 // Insert the methods from module override in override
 $copy_from = array_slice($module_file, $module_class->getStartLine() + 1, $module_class->getEndLine() - $module_class->getStartLine() - 2);
 array_splice($override_file, $override_class->getEndLine() - 1, 0, $copy_from);
 $code = implode('', $override_file);
 file_put_contents($override_path, $code);
 return true;
}

 

/**
 * Remove all methods in a module override from the override class
 *
 * @param string $classname
 * @return bool
 */
public function removeOverride($classname)
{
 $path = Autoload::getInstance()->getClassPath($classname.'Core');
 if (!Autoload::getInstance()->getClassPath($classname))
  return true;

 // Check if override file is writable
 $override_path = _PS_ROOT_DIR_.'/'.Autoload::getInstance()->getClassPath($classname);
 if (!is_writable($override_path))
  return false;
 // Make a reflection of the override class and the module override class
 $override_file = file($override_path);
 eval(preg_replace(array('#^\s*<\?php#', '#class\s+'.$classname.'\s+extends\s+([a-z0-9_]+)(\s+implements\s+([a-z0-9_]+))?#i'), array('', 'class '.$classname.'OverrideOriginal_remove'), implode('', $override_file)));
 $override_class = new ReflectionClass($classname.'OverrideOriginal_remove');
 $module_file = file($this->getLocalPath().'override/'.$path);
 eval(preg_replace(array('#^\s*<\?php#', '#class\s+'.$classname.'(\s+extends\s+([a-z0-9_]+)(\s+implements\s+([a-z0-9_]+))?)?#i'), array('', 'class '.$classname.'Override_remove'), implode('', $module_file)));
 $module_class = new ReflectionClass($classname.'Override_remove');
 // Remove methods from override file
 $override_file = file($override_path);
 foreach ($module_class->getMethods() as $method)
 {
  if (!$override_class->hasMethod($method->getName()))
   continue;
  $method = $override_class->getMethod($method->getName());
  $length = $method->getEndLine() - $method->getStartLine() + 1;
  array_splice($override_file, $method->getStartLine() - 1, $length, array_pad(array(), $length, '#--remove--#'));
 }
 // Remove properties from override file
 foreach ($module_class->getProperties() as $property)
 {
  if (!$override_class->hasProperty($property->getName()))
   continue;
  // Remplacer la ligne de déclaration par "remove"
  foreach ($override_file as $line_number => &$line_content)
   if (preg_match('/(public|private|protected)\s+(static\s+)?\$'.$property->getName().'/i', $line_content))
   {
 $line_content = '#--remove--#';
 break;
   }
 }
 // Rewrite nice code
 $code = '';
 foreach ($override_file as $line)
 {
  if ($line == '#--remove--#')
   continue;
  $code .= $line;
 }
 file_put_contents($override_path, $code);
 return true;
}

 

A la première lecture du code, il semblerait qu'il soit possible d'écrire du code qui sera "retiré" par la suite. Je propose qu'on discute ici et commente ces deux méthodes pour une meilleure utilisation de celles-ci.

 

Je les lirais plus en profondeur et réaliserais des tests pour voir le fonctionnement de celles-ci.

  • Like 1

Share this post


Link to post
Share on other sites

oui c'est ce que j'ai déjà expliqué:

il suffit de mettre un dossier override dans le dossier modules : http://www.prestasho...post__p__969817

 

ces fonctions permettent d'installer et de désinstaller des modules ayant les mêmes classes avec des fonctions différentes SANS passer par le FTP (évidemment si tu installes un override contenant une fonction qui est déjà overridé il faut le faire par FTP et c'est la seule limitation) :

http://www.prestashop.com/forums/index.php?/topic/195568-moduleoverride-gratuit-theme-switcher/page__view__findpost__p__969828 :

il n'y a qu'une seule limite : le nouveau module contient une fonction dans un override qui est déjà installé dans l'override de la boutique.

 

J'ai une boutique test en local avec une quinzaine de modules que je viens de mettre à jour et aucun soucis, j'installe un module j'en désinstalle un autre, tout est automatisé et se passe à merveille...

Edited by coeos.pro (see edit history)

Share this post


Link to post
Share on other sites

On est d'accord, mais... qu'en est-il du code que j'ai mis dans le premier message ? Je peux y voir figurer du _remove, et ainsi de suite. Le fait de mettre l'override dans un dossier, c'est déjà dit, là. L'intéressant est de discuter de la manière propre et correcte d'utiliser ce code, éventuellement ! ;)

Share this post


Link to post
Share on other sites

Bonjour,

 

j'ai beau me dire que tout est possible et coes.pro nous le prouve chaque jours, j'ai du mal à faire confiance à 100% à une gestion automatisé des overides multiples de différents modules. Mais plus parce que je ne fait pas confiance au multiple développeur arrivant sur la solution et nous proposant leur vision plus ou moins académique du développement.

 

N'étant mois même pas assez chevronné sur la maitrise du code objet et de cette nouvelle structure apparue sur la 1.5 je ne m'aventurerais pas à donner une analyse du code, mais juste une expérience sur l'utilisation de ces fonctionnalités qui peuvent être risqués, si mal utilisées.

 

Mais peut être que vous arriverais à me convaincre que le codage de cette fonction arrivera à gérer tous les cas possibles.

Share this post


Link to post
Share on other sites

Je voulais justement voir, au travers d'une bonne (et véritable) analyse, si il était possible de fournir une sureté dans l'utilisation de cette mécanique. Et voir si on ne peut pas proposer une solution alternative (tel qu'un nom comme proposé par Damien, à savoir ClassNameOverride<NomDuModule> ; par exemple). Mais pour ça, je voudrais être sur des possibilités déjà offertes par ces petits bouts de codes, qui vont bien plus loin que le simple fait de glisser des overrides dans un dossier, :)

  • Like 1

Share this post


Link to post
Share on other sites

j'ai fait pas mal de tests avec une quinzaine de modules avec et sans override, avec 1 et plusieurs override, avec plusieurs fonctions dans certains override, et je n'ai rencontré aucun problème aussi bien en installation qu'en désinstallation de modules... à vous de tester maintenant

Share this post


Link to post
Share on other sites

Ok, on a donc tous compris: coes.pro a testé et analysé le code pour nous, mais on peut compter sur le fait qu'il n'en dira pas plus. Je ferais cela dans un futur proche (demain, grosso modo) et vous transmettrais mes analyses/conclusions. On pourra faire avancer aussi bien le débat que la documentation, je l'espère...

Share this post


Link to post
Share on other sites

Commenter, le code, par exemple. C'est justement que tu sembles ne pas avoir lu le code ou pris la peine de voir ce qu'il proposait, d'aller plus loin. Je vois beaucoup de choses à dire de plus, mais avant de m'avancer là-dessus, je dois mieux analyser le code et faire des tests.

 

Rien que le _remove ou encore #--remove--# à eux seuls m'intrigue. Si ce n'est pas ton cas, alors oui, il n'y a rien à dire de plus de ta part.

Share this post


Link to post
Share on other sites

  • 2 weeks later...

Quelques nouvelles, c'est une ligne tout droit venue de la version SVN:

  //$this->uninstallOverrides(); remove this line because if module a install an override, then module b install same override, this line will remove override of module a (if you find a bug related to this line please don't forget what i say before)

 

A en croire ceci, cette méthode pose problème. On peut donc, très nettement, se renseigner sur ces méthodes plus loin que le fait de dire que, oui, cela fonctionne (mais jusqu'à quel moment, ça... !) ;)

Share this post


Link to post
Share on other sites

  • 3 months later...

Salut,

 

Je commence à peine à utiliser cette fonctionnalité et j'ai déjà repéré quelques bugs:

 

- l'installation ce passe plutôt bien mise à part que les fichiers thème ne sont pas automatiquement surchargé, j'ai du bricoler un truc pour que les fichiers soit copiés dans le dossier override de Prestashop

 

- Le ménages n'est pas fait complètement lors de la désinstallation, il reste tous ce qui est commentaire de méthode (pas trop gênant) et les définitions de constante dans la classe ne sont pas supprimés non plus (c'est déjà plus gênant)

 

J'ai un module à réaliser et crois que je vais bien m'amuser.

 

Franck

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