DDC-29: ProxyClassGenerator does not correctly override methods with type-hinted array or default values or pass by reference #3657

Closed
doctrinebot opened this Issue Oct 2, 2009 · 2 comments

1 participant

@doctrinebot

Jira issue originally created by user itoijala:

The ProxyClassGenerator does not take into account array type-hinting, default values or pass by reference.

Example:

public function exampleMethod(array $array, &$c, $a = 'foo', array $b = array('b'))
{
    /** ... **/
}

Creates the follwing code:

public function exampleMethod($array, $c, $a, $b) 
{
    $this->_load();
    return parent::exampleMethod($array, $c, $a, $b);
}

and the following warning:

Strict Standards: Declaration of Doctrine\Generated\Proxies\Model*User_UserAProxy::exampleMethod() should be compatible with that of Model\User\User::exampleMethod() in C:\Windows\Temp\Model_User*UserAProxy.g.php on line 200

I am not sure about the consequences other than the warning when using E_STRICT.

The fix seems to be relatively simple:

Modify the _generateMethods method in ProxyClassGenerator

OLD:

private function _generateMethods(ClassMetadata $class)
    {
        $methods = '';

        foreach ($class->reflClass->getMethods() as $method) {
            if ($method->isConstructor()) {
                continue;
            }

            if ($method->isPublic() && ! $method->isFinal() && !$method->isStatic()) {
                $methods .= PHP_EOL . 'public function ' . $method->getName() . '(';
                $firstParam = true;
                $parameterString = $argumentString = '';

                foreach ($method->getParameters() as $param) {
                    if ($firstParam) {
                        $firstParam = false;
                    } else {
                        $parameterString .= ', ';
                        $argumentString  .= ', ';
                    }

                    // We need to pick the type hint class too
                    if (($paramClass = $param->getClass()) !== null) {
                        $parameterString .= '\\' . $paramClass->getName() . ' ';
                    }

                    $parameterString .= '$' . $param->getName();
                    $argumentString  .= '$' . $param->getName();
                }

                $methods .= $parameterString . ') {' . PHP_EOL;
                $methods .= '$this->*load();' . PHP*EOL;
                $methods .= 'return parent::' . $method->getName() . '(' . $argumentString . ');';
                $methods .= '}' . PHP_EOL;
            }
        }

        return $methods;
    }

NEW:

private function _generateMethods(ClassMetadata $class)
    {
        $methods = '';

        foreach ($class->reflClass->getMethods() as $method) {
            if ($method->isConstructor()) {
                continue;
            }

            if ($method->isPublic() && ! $method->isFinal() && !$method->isStatic()) {
                $methods .= PHP_EOL . 'public function ' . $method->getName() . '(';
                $firstParam = true;
                $parameterString = $argumentString = '';

                foreach ($method->getParameters() as $param) {
                    if ($firstParam) {
                        $firstParam = false;
                    } else {
                        $parameterString .= ', ';
                        $argumentString  .= ', ';
                    }

                    // We need to pick the type hint class too
                    if (($paramClass = $param->getClass()) !== null) {
                        $parameterString .= '\\' . $paramClass->getName() . ' ';
                    }
                    _* else if ($param->isArray())
                    {
                        $parameterString .= 'array ';
                    } *_

                    _* if ($param->isPassedByReference())
                    {
                        $parameterString .= '&';
                    } *_
                    $parameterString .= '$' . $param->getName();
                    _* if ($param->isDefaultValueAvailable())
                    {
                        $parameterString .= ' = ' . var_export($param->getDefaultValue(), true);
                    } *_
                    $argumentString  .= '$' . $param->getName();
                }

                $methods .= $parameterString . ') {' . PHP_EOL;
                $methods .= '$this->*load();' . PHP*EOL;
                $methods .= 'return parent::' . $method->getName() . '(' . $argumentString . ');';
                $methods .= '}' . PHP_EOL;
            }
        }

        return $methods;
    }

EDIT: forgot to add the fix for pass by reference.
EDIT2: fixed typo.

@doctrinebot

Comment created by romanb:

formatting

@doctrinebot

Issue was closed with resolution "Fixed"

@doctrinebot doctrinebot added this to the 2.0-ALPHA2 milestone Dec 6, 2015
@doctrinebot doctrinebot closed this Dec 6, 2015
@doctrinebot doctrinebot added the Bug label Dec 7, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment