Override folder functionality and conflicts?

552 views Asked by At

Override folder functionality and conflicts?

I have a class file called group.php in the prestashop base code. I want to add a new field and make some functional changes to that group.php file.

I have created a custom module and did those changes there. When i install that module, my inherited group.php file is sent to the Base Override folder and stays there.

Now my question is,

How that override functionality is working?

How the conflicts are managed by prestashop?

For eg: I have 2 modules which are seperately overriding the same file group.php. If i install those 2 module simultaneously which group.php will be there in the base override folder?

2

There are 2 answers

0
Knowband Plugins On

When two modules are overriding the same file then PrestaShop adds a comment at the top of overridden function(s) to identify which function in overridden by which module.

Example of that comment is:

/*
* module: supercheckout
* date: 2016-12-01 08:03:28
* version: 1.0.1
*/
public function overriddenFunction()
{
    parent::mylogout();
    -- Custom Code Here --
}

You can check this in the overridden file on your end (/override/classes/group.php) in your case.

The overridden code is then remove using these comments only when any module is uninstalled and if only a single module is overriding the module then the file gets deleted.

0
Florian Lemaitre On

Here is the addOverride() method from Module class:

/**
 * 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);
        // Re-generate the class index
        Autoload::getInstance()->generateIndex();
        return true;
    }

    // Check if override file is writable
    $override_path = _PS_ROOT_DIR_.'/'.Autoload::getInstance()->getClassPath($classname);
    if ((!file_exists($override_path) && !is_writable(dirname($override_path))) || (file_exists($override_path) && !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;
}

As stated in the comments conflicts are handle at method and properties scale.

If you try to install a module that override a new method or a new property, everything will work fine and the two files will be combined.

If you try to install a module that override a method already overridden by a different module the installation will fail.