覆盖文件夹功能和冲突?

时间:2017-01-05 06:08:59

标签: php inheritance override prestashop prestashop-1.5

覆盖文件夹功能和冲突?

我在prestashop基本代码中有一个名为group.php的类文件。 我想添加一个新字段,并对该group.php文件进行一些功能更改。

我创建了一个自定义模块并在那里进行了那些更改。当我安装该模块时,我继承的group.php文件将被发送到Base Override文件夹并保留在那里。

现在我的问题是,

覆盖功能如何运作?

prestashop如何管理冲突?

例如:我有2个模块,它们单独覆盖同一个文件group.php。 如果我同时安装那两个$data->{'data-val'}->$johndoe; 将存在于基本覆盖文件夹中的模块?

2 个答案:

答案 0 :(得分:3)

以下是addOverride()类的Module方法:

/**
 * 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;
}

正如评论中所述,冲突是在方法和属性规模上处理的。

如果您尝试安装覆盖新方法或新属性的模块,一切都会正常工作,两个文件将合并。

如果您尝试安装覆盖已被其他模块覆盖的方法的模块,则安装将失败。

答案 1 :(得分:2)

当两个模块覆盖同一个文件时,PrestaShop会在覆盖函数的顶部添加注释,以识别哪个模块被哪个模块覆盖。

该评论的示例是:

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

您可以在您的结尾(/override / classes / group.php)中的重写文件中进行检查。

只有在卸载任何模块并且只有一个模块覆盖模块时,才会使用这些注释删除被覆盖的代码,然后删除该文件。