Doctrine 2 - ORM
  1. Doctrine 2 - ORM
  2. DDC-29

ProxyClassGenerator does not correctly override methods with type-hinted array or default values or pass by reference

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Minor Minor
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 2.0-ALPHA2
    • Component/s: ORM
    • Security Level: All
    • Labels:
      None

      Description

      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.

        Activity

        Hide
        Roman S. Borschel added a comment -

        formatting

        Show
        Roman S. Borschel added a comment - formatting

          People

          • Assignee:
            Roman S. Borschel
            Reporter:
            Ismo Toijala
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: