Example #1
0
 /**
  * Implements the loading of the class object
  *
  * @throws Exception if the class is already generated(not null)
  */
 protected function generateClass()
 {
     parent::generateClass();
     // If it is child type, fallback to ComplexType. Can check this only when all
     // types are loaded. See Generator->loadTypes();
     if ($this->getBaseTypeClass() === null) {
         $this->implementArrayInterfaces();
     }
 }
 /**
  * Determine parent class
  *
  * @return string|null
  *   Returns a string containing the PHP identifier for the parent class
  *   or null if there is no applicable parent class.
  */
 public function getBaseTypeClass()
 {
     // If we have a base type which is different than the current class then extend that.
     // It is actually possible to have different classes with the same name as PHP SoapClient has a poor
     // understanding of namespaces. Two types with the same name but in different namespaces will have the same
     // identifier.
     if ($this->baseType !== null && $this->baseType !== $this) {
         return $this->baseType->getPhpIdentifier();
     }
     return null;
 }
 /**
  * Setup and return a service with operations and types.
  *
  * @return Service
  */
 private function givenServiceWithOperations()
 {
     // Response GetBook types
     $responseBookName = new ComplexType($this->config, 'Method_Get_Book_Response_BOOK_BOOK_NAME');
     $responseBookName->addMember('string', 'bookName', false);
     $responseBook = new ComplexType($this->config, 'Method_Get_Book_Response_BOOK');
     $responseBook->addMember('int', 'bookId', false);
     // Base type example
     $responseBook->setBaseType($responseBookName);
     $returnGetBookType = new ComplexType($this->config, 'Get_Book_Type_Response');
     $returnGetBookType->addMember('Method_Get_Book_Response_BOOK', 'book_response', false);
     // Request GetBook types
     $bookType = new Enum($this->config, 'Book_Type_Enumeration', 'string');
     $bookType->addValue('fiction');
     $bookType->addValue('comedy');
     $requestBook = new ComplexType($this->config, 'Method_Get_Book_Request_BOOK');
     $requestBook->addMember('int', 'bookId', false);
     $requestBook->addMember('Book_Type_Enumeration', 'genre', false);
     $requestGetBook = new ComplexType($this->config, 'Get_Book_Type_Request');
     $requestGetBook->addMember('Method_Get_Book_Request_BOOK', 'book_request', false);
     // Operation GetBook
     $getBookOperation = new Operation('GetBook', 'Get_Book_Type_Request $request', 'Get Book', 'Get_Book_Type_Response');
     // Response GetAuthors type
     $responseAuthor = new ComplexType($this->config, 'Get_Authors_Response_Author');
     $responseAuthor->addMember('int', 'authorId', false);
     $responseAuthor->addMember('string', 'authorName', false);
     $returnGetAuthors = new ComplexType($this->config, 'Method_Get_Authors_Response');
     $returnGetAuthors->addMember('Get_Authors_Response_Author[]', 'Get_Authors_Response_Author', false);
     // Request GetAuthors type
     $requestGetAuthor = new ComplexType($this->config, 'Method_Get_Authors_Request');
     $requestGetAuthor->addMember('Method_Get_Book_Request_BOOK', 'book_request', false);
     // Operation GetAuthors
     $getAuthorsOperator = new Operation('GetAuthor', 'Method_Get_Authors_Request $request', 'Get Authors', 'Method_Get_Authors_Response');
     // Service creation
     $types = array($responseBookName, $responseBook, $returnGetBookType, $requestBook, $requestGetBook, $responseAuthor, $returnGetAuthors, $requestGetAuthor, $bookType);
     $service = new Service($this->config, 'Book_Shell', $types, 'Book shells');
     $service->addOperation($getBookOperation);
     $service->addOperation($getAuthorsOperator);
     return $service;
 }
 /**
  * Implements the loading of the class object
  *
  * @throws Exception if the class is already generated(not null)
  */
 protected function generateClass()
 {
     if ($this->class != null) {
         throw new Exception("The class has already been generated");
     }
     // Determine parent class
     $classBaseType = null;
     // If we have a base type which is different than the current class then extend that.
     // It is actually possible to have different classes with the same name as PHP SoapClient has a poor
     // understanding of namespaces. Two types with the same name but in different namespaces will have the same
     // identifier.
     if ($this->baseType !== null && $this->baseType !== $this) {
         $classBaseType = $this->baseType->getPhpIdentifier();
     }
     $class = new PhpClass($this->phpIdentifier, false, $classBaseType, null, false, $this->abstract);
     $constructorComment = new PhpDocComment();
     $constructorSource = '';
     $constructorParameters = array();
     $accessors = array();
     // Add base type members to constructor parameter list first and call base class constructor
     $parentMembers = $this->getBaseTypeMembers($this);
     if (!empty($parentMembers)) {
         foreach ($parentMembers as $member) {
             $type = Validator::validateType($member->getType());
             $name = Validator::validateAttribute($member->getName());
             if (!$member->getNullable()) {
                 $constructorComment->addParam(PhpDocElementFactory::getParam($type, $name, ''));
                 $constructorParameters[$name] = Validator::validateTypeHint($type);
             }
         }
         $constructorSource .= '  parent::__construct(' . $this->buildParametersString($constructorParameters, false) . ');' . PHP_EOL;
     }
     // Add member variables
     foreach ($this->members as $member) {
         $type = Validator::validateType($member->getType());
         $name = Validator::validateAttribute($member->getName());
         $typeHint = Validator::validateTypeHint($type);
         $comment = new PhpDocComment();
         $comment->setVar(PhpDocElementFactory::getVar($type, $name, ''));
         $var = new PhpVariable('protected', $name, 'null', $comment);
         $class->addVariable($var);
         if (!$member->getNullable()) {
             if ($type == '\\DateTime') {
                 if ($this->config->get('constructorParamsDefaultToNull')) {
                     $constructorSource .= '  $this->' . $name . ' = $' . $name . ' ? $' . $name . '->format(\\DateTime::ATOM) : null;' . PHP_EOL;
                 } else {
                     $constructorSource .= '  $this->' . $name . ' = $' . $name . '->format(\\DateTime::ATOM);' . PHP_EOL;
                 }
             } else {
                 $constructorSource .= '  $this->' . $name . ' = $' . $name . ';' . PHP_EOL;
             }
             $constructorComment->addParam(PhpDocElementFactory::getParam($type, $name, ''));
             $constructorParameters[$name] = $typeHint;
         }
         $getterComment = new PhpDocComment();
         $getterComment->setReturn(PhpDocElementFactory::getReturn($type, ''));
         $getterCode = '';
         if ($type == '\\DateTime') {
             $getterCode = '  if ($this->' . $name . ' == null) {' . PHP_EOL . '    return null;' . PHP_EOL . '  } else {' . PHP_EOL . '    try {' . PHP_EOL . '      return new \\DateTime($this->' . $name . ');' . PHP_EOL . '    } catch (\\Exception $e) {' . PHP_EOL . '      return false;' . PHP_EOL . '    }' . PHP_EOL . '  }' . PHP_EOL;
         } else {
             $getterCode = '  return $this->' . $name . ';' . PHP_EOL;
         }
         $getter = new PhpFunction('public', 'get' . ucfirst($name), '', $getterCode, $getterComment);
         $accessors[] = $getter;
         $setterComment = new PhpDocComment();
         $setterComment->addParam(PhpDocElementFactory::getParam($type, $name, ''));
         $setterComment->setReturn(PhpDocElementFactory::getReturn($this->phpNamespacedIdentifier, ''));
         $setterCode = '';
         if ($type == '\\DateTime') {
             if ($member->getNullable()) {
                 $setterCode = '  if ($' . $name . ' == null) {' . PHP_EOL . '   $this->' . $name . ' = null;' . PHP_EOL . '  } else {' . PHP_EOL . '    $this->' . $name . ' = $' . $name . '->format(\\DateTime::ATOM);' . PHP_EOL . '  }' . PHP_EOL;
             } else {
                 $setterCode = '  $this->' . $name . ' = $' . $name . '->format(\\DateTime::ATOM);' . PHP_EOL;
             }
         } else {
             $setterCode = '  $this->' . $name . ' = $' . $name . ';' . PHP_EOL;
         }
         $setterCode .= '  return $this;' . PHP_EOL;
         $setter = new PhpFunction('public', 'set' . ucfirst($name), $this->buildParametersString(array($name => $typeHint), true, $member->getNullable() && !empty($typeHint)), $setterCode, $setterComment);
         $accessors[] = $setter;
     }
     $constructor = new PhpFunction('public', '__construct', $this->buildParametersString($constructorParameters, true, $this->config->get('constructorParamsDefaultToNull')), $constructorSource, $constructorComment);
     $class->addFunction($constructor);
     foreach ($accessors as $accessor) {
         $class->addFunction($accessor);
     }
     $this->class = $class;
 }
 /**
  * Implements the loading of the class object
  *
  * @throws Exception if the class is already generated(not null)
  */
 protected function generateClass()
 {
     if ($this->class != null) {
         throw new Exception("The class has already been generated");
     }
     $class = new PhpClass($this->phpIdentifier, false, $this->baseType !== null ? $this->baseType->getPhpIdentifier() : '');
     $constructorComment = new PhpDocComment();
     $constructorSource = '';
     $constructorParameters = array();
     $accessors = array();
     // Add base type members to constructor parameter list first and call base class constructor
     $parentMembers = $this->getBaseTypeMembers($this);
     if (!empty($parentMembers)) {
         foreach ($parentMembers as $member) {
             $type = Validator::validateType($member->getType());
             $name = Validator::validateAttribute($member->getName());
             if (!$member->getNullable()) {
                 $constructorComment->addParam(PhpDocElementFactory::getParam($type, $name, ''));
                 $constructorParameters[$name] = Validator::validateTypeHint($type);
             }
         }
         $constructorSource .= '  parent::__construct(' . $this->buildParametersString($constructorParameters, false) . ');' . PHP_EOL;
     }
     // Add member variables
     foreach ($this->members as $member) {
         $type = Validator::validateType($member->getType());
         $name = Validator::validateAttribute($member->getName());
         $typeHint = Validator::validateTypeHint($type);
         $comment = new PhpDocComment();
         $comment->setVar(PhpDocElementFactory::getVar($type, $name, ''));
         $var = new PhpVariable('protected', $name, 'null', $comment);
         $class->addVariable($var);
         if (!$member->getNullable()) {
             if ($type == '\\DateTime') {
                 if ($this->config->get('constructorParamsDefaultToNull')) {
                     // GT Mod - removed DateTime::ATOM date (not compatible with apollo) with Y-m-d\TH:i:s .
                     $constructorSource .= '  $this->' . $name . ' = $' . $name . ' ? $' . $name . '->format(\'Y-m-d\\TH:i:s\\Z\') : null;' . PHP_EOL;
                 } else {
                     // GT Mod - removed DateTime::ATOM date (not compatible with apollo) with Y-m-d\TH:i:s .
                     $constructorSource .= '  $this->' . $name . ' = $' . $name . '->format(\'Y-m-d\\TH:i:s\\Z\');' . PHP_EOL;
                 }
             } else {
                 $constructorSource .= '  $this->' . $name . ' = $' . $name . ';' . PHP_EOL;
             }
             $constructorComment->addParam(PhpDocElementFactory::getParam($type, $name, ''));
             $constructorParameters[$name] = $typeHint;
         }
         $getterComment = new PhpDocComment();
         $getterComment->setReturn(PhpDocElementFactory::getReturn($type, ''));
         $getterCode = '';
         if ($type == '\\DateTime') {
             $getterCode = '  if ($this->' . $name . ' == null) {' . PHP_EOL . '    return null;' . PHP_EOL . '  } else {' . PHP_EOL . '    try {' . PHP_EOL . '      return new \\DateTime($this->' . $name . ');' . PHP_EOL . '    } catch (\\Exception $e) {' . PHP_EOL . '      return false;' . PHP_EOL . '    }' . PHP_EOL . '  }' . PHP_EOL;
         } else {
             $getterCode = '  return $this->' . $name . ';' . PHP_EOL;
         }
         $getter = new PhpFunction('public', 'get' . ucfirst($name), '', $getterCode, $getterComment);
         $accessors[] = $getter;
         $setterComment = new PhpDocComment();
         $setterComment->addParam(PhpDocElementFactory::getParam($type, $name, ''));
         $setterComment->setReturn(PhpDocElementFactory::getReturn($this->phpNamespacedIdentifier, ''));
         $setterCode = '';
         if ($type == '\\DateTime') {
             // GT Mod - removed DateTime::ATOM date (not compatible with apollo) with Y-m-d\TH:i:sZ .
             $setterCode = '  $this->' . $name . ' = $' . $name . '->format(\'Y-m-d\\TH:i:s\\Z\');' . PHP_EOL;
         } else {
             $setterCode = '  $this->' . $name . ' = $' . $name . ';' . PHP_EOL;
         }
         $setterCode .= '  return $this;' . PHP_EOL;
         $setter = new PhpFunction('public', 'set' . ucfirst($name), $this->buildParametersString(array($name => $typeHint)), $setterCode, $setterComment);
         $accessors[] = $setter;
     }
     $constructor = new PhpFunction('public', '__construct', $this->buildParametersString($constructorParameters, true, $this->config->get('constructorParamsDefaultToNull')), $constructorSource, $constructorComment);
     $class->addFunction($constructor);
     foreach ($accessors as $accessor) {
         $class->addFunction($accessor);
     }
     $this->class = $class;
 }
 /**
  * Loads all type classes
  */
 protected function loadTypes()
 {
     $this->log('Loading types');
     $types = $this->wsdl->getTypes();
     foreach ($types as $typeNode) {
         $type = null;
         if ($typeNode->isComplex()) {
             $type = new ComplexType($this->config, $typeNode->getName());
             $this->log('Loading type ' . $type->getPhpIdentifier());
             $type->setAbstract($typeNode->isAbstract());
             foreach ($typeNode->getParts() as $name => $typeName) {
                 // There are 2 ways a wsdl can indicate that a field accepts the null value -
                 // by setting the "nillable" attribute to "true" or by setting the "minOccurs" attribute to "0".
                 // See http://www.ibm.com/developerworks/webservices/library/ws-tip-null/index.html
                 $nullable = $typeNode->isElementNillable($name) || $typeNode->getElementMinOccurs($name) === 0;
                 $type->addMember($typeName, $name, $nullable);
             }
         } elseif ($enumValues = $typeNode->getEnumerations()) {
             $type = new Enum($this->config, $typeNode->getName(), $typeNode->getRestriction());
             array_walk($enumValues, function ($value) use($type) {
                 $type->addValue($value);
             });
         } elseif ($pattern = $typeNode->getPattern()) {
             $type = new Pattern($this->config, $typeNode->getName(), $typeNode->getRestriction());
             $type->setValue($pattern);
         }
         if ($type != null) {
             $already_registered = false;
             if ($this->config->get('sharedTypes')) {
                 foreach ($this->types as $registered_types) {
                     if ($registered_types->getIdentifier() == $type->getIdentifier()) {
                         $already_registered = true;
                         break;
                     }
                 }
             }
             if (!$already_registered) {
                 $this->types[$typeNode->getName()] = $type;
             }
         }
     }
     // Loop through all types again to setup class inheritance.
     // We can only do this once all types have been loaded. Otherwise we risk referencing types which have not been
     // loaded yet.
     foreach ($types as $type) {
         if (($baseType = $type->getBase()) && isset($this->types[$baseType]) && $this->types[$baseType] instanceof ComplexType) {
             $this->types[$type->getName()]->setBaseType($this->types[$baseType]);
         }
     }
     $this->log('Done loading types');
 }
 /**
  * Test classes that extend themselves.
  */
 public function testExtendingOwnClass()
 {
     // It is actually possible to have a type which extends itself. This is caused by the poor understanding of PHP
     // namespaces. Two types with the same name but in different namespaces will have the same identifier.
     $config = new Config(array('inputFile' => null, 'outputDir' => null));
     $type = new ComplexType($config, 'ExtendOwn');
     $type->setBaseType($type);
     $this->generateClass($type);
     $object = new \ExtendOwn();
     $class = new \ReflectionClass($object);
     $this->assertEmpty($class->getParentClass());
 }
 /**
  * Test setters for nullable typed members.
  */
 public function testNullableTypedMembers()
 {
     $config = new Config(array('inputFile' => null, 'outputDir' => null));
     $type = new ComplexType($config, 'NullableDateTime');
     // Add a member which has a type (datetime) and is nullable.
     $type->addMember('datetime', 'aDateTime', true);
     $this->generateClass($type);
     $object = new \NullableDateTime();
     // If the member is nullable then we should also be able to pass null to the setter without causing an error.
     $object->setADateTime(null);
     // Obviously the returned member value should be null as well.
     $this->assertNull($object->getADateTime());
 }
 /**
  * Implements the loading of the class object
  *
  * @throws Exception if the class is already generated(not null)
  */
 protected function generateClass()
 {
     if ($this->class != null) {
         throw new Exception("The class has already been generated");
     }
     $class = new PhpClass($this->phpIdentifier, $this->config->getClassExists(), $this->baseType !== null ? $this->baseType->getPhpIdentifier() : '');
     // Add the base class as a dependency. Otherwise we risk referencing an undefined class.
     if (!empty($this->baseType) && !$this->config->getOneFile() && !$this->config->getNoIncludes()) {
         $class->addDependency($this->baseType->getIdentifier() . '.php');
     }
     $constructorComment = new PhpDocComment();
     $constructorComment->setAccess(PhpDocElementFactory::getPublicAccess());
     $constructorSource = '';
     $constructorParameters = '';
     $accessors = array();
     // Add base type members to constructor parameter list first and call base class constructor
     if ($this->baseType !== null) {
         foreach ($this->baseType->getMembers() as $member) {
             $type = Validator::validateType($member->getType());
             $name = Validator::validateAttribute($member->getName());
             if (!$member->getNillable()) {
                 $constructorComment->addParam(PhpDocElementFactory::getParam($type, $name, ''));
                 $constructorComment->setAccess(PhpDocElementFactory::getPublicAccess());
                 $constructorParameters .= ', $' . $name;
             }
         }
         $constructorSource .= '  parent::__construct(' . substr($constructorParameters, 2) . ');' . PHP_EOL;
     }
     // Add member variables
     foreach ($this->members as $member) {
         $type = Validator::validateType($member->getType());
         $name = Validator::validateAttribute($member->getName());
         $comment = new PhpDocComment();
         $comment->setVar(PhpDocElementFactory::getVar($type, $name, ''));
         $comment->setAccess(PhpDocElementFactory::getPublicAccess());
         $var = new PhpVariable('public', $name, 'null', $comment);
         $class->addVariable($var);
         if (!$member->getNillable()) {
             $constructorSource .= '  $this->' . $name . ' = $' . $name . ';' . PHP_EOL;
             $constructorComment->addParam(PhpDocElementFactory::getParam($type, $name, ''));
             $constructorComment->setAccess(PhpDocElementFactory::getPublicAccess());
             $constructorParameters .= ', $' . $name;
             if ($this->config->getConstructorParamsDefaultToNull()) {
                 $constructorParameters .= ' = null';
             }
             if ($this->config->getCreateAccessors()) {
                 $getterComment = new PhpDocComment();
                 $getterComment->setReturn(PhpDocElementFactory::getReturn($type, ''));
                 $getter = new PhpFunction('public', 'get' . ucfirst($name), '', '  return $this->' . $name . ';' . PHP_EOL, $getterComment);
                 $accessors[] = $getter;
                 $setterComment = new PhpDocComment();
                 $setterComment->addParam(PhpDocElementFactory::getParam($type, $name, ''));
                 $setter = new PhpFunction('public', 'set' . ucfirst($name), '$' . $name, '  $this->' . $name . ' = $' . $name . ';' . PHP_EOL, $setterComment);
                 $accessors[] = $setter;
             }
         }
     }
     $constructorParameters = substr($constructorParameters, 2);
     // Remove first comma
     $function = new PhpFunction('public', '__construct', $constructorParameters, $constructorSource, $constructorComment);
     // Only add the constructor if type constructor is selected
     if ($this->config->getNoTypeConstructor() == false) {
         $class->addFunction($function);
     }
     foreach ($accessors as $accessor) {
         $class->addFunction($accessor);
     }
     $this->class = $class;
 }
 /**
  * Loads all type classes
  */
 private function loadTypes()
 {
     $this->log('Loading types');
     $types = $this->wsdl->getTypes();
     foreach ($types as $typeNode) {
         if ($typeNode->isArray()) {
             // skip arrays
             continue;
         }
         $type = null;
         if ($typeNode->isComplex()) {
             $type = new ComplexType($this->config, $typeNode->getName());
             $this->log('Loading type ' . $type->getPhpIdentifier());
             foreach ($typeNode->getParts() as $name => $typeName) {
                 $type->addMember($typeName, $name, $typeNode->isElementNillable($name));
             }
         } elseif ($enumValues = $typeNode->getEnumerations()) {
             $type = new Enum($this->config, $typeNode->getName(), $typeNode->getRestriction());
             array_walk($enumValues, function ($value) use($type) {
                 $type->addValue($value);
             });
         } elseif ($pattern = $typeNode->getPattern()) {
             $type = new Pattern($this->config, $typeNode->getName(), $typeNode->getRestriction());
             $type->setValue($pattern);
         }
         if ($type != null) {
             $already_registered = false;
             if ($this->config->getSharedTypes()) {
                 foreach ($this->types as $registered_types) {
                     if ($registered_types->getIdentifier() == $type->getIdentifier()) {
                         $already_registered = true;
                         break;
                     }
                 }
             }
             if (!$already_registered) {
                 $this->types[$typeNode->getName()] = $type;
             }
         }
     }
     // Loop through all types again to setup class inheritance.
     // We can only do this once all types have been loaded. Otherwise we risk referencing types which have not been
     // loaded yet.
     foreach ($types as $type) {
         if (($baseType = $type->getBase()) && isset($this->types[$baseType])) {
             $this->types[$type->getName()]->setBaseType($this->types[$baseType]);
         }
     }
     $this->log('Done loading types');
 }
 /**
  * Test fluent setters.
  */
 public function testFluentSetters()
 {
     $config = new Config(array('inputFile' => null, 'outputDir' => null));
     $complexType = new ComplexType($config, 'Fluent');
     $complexType->addMember('string', 'attribute', true);
     $this->generateClass($complexType);
     // When calling a setter the returned value should be the same as the
     // object where the setter was called.
     $object = new \Fluent();
     $returnValue = $object->setAttribute('value');
     $this->assertEquals($object, $returnValue);
     // The setter should also have its own class as its return type.
     $class = new \ReflectionClass($object);
     $this->assertMethodHasReturnType($class->getMethod('setAttribute'), $class->getName());
 }