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