/** * {@inheritdoc} */ public function createClassmap() { /* * INI FILE GENERATION */ $outputPath = array($this->config->getOutputPath()); // if the psr0 autoloader has been selected, transform the class namespace into a filesystem path if ($this->config->getAutoloader() === Config::AUTOLOADER_PSR0) { $outputPath[] = str_ireplace('\\', DIRECTORY_SEPARATOR, $this->config->getNamespace()); } // append the file name $outputPath[] = 'classmap.ini'; // finalize the output path $outputPath = implode(DIRECTORY_SEPARATOR, $outputPath); // remove the file if exists $fs = new Filesystem(); $fs->remove($outputPath); foreach ($this->classmap as $wsdlType => $phpType) { file_put_contents($outputPath, "{$wsdlType} = {$phpType}" . AbstractGenerator::LINE_FEED, FILE_APPEND); } /* * CLASS GENERATION */ // create the class $class = ClassGenerator::fromReflection(new ClassReflection('\\Sapone\\Template\\ClassmapTemplate')); $class->setName('Classmap'); $class->setExtendedClass('\\ArrayObject'); $class->setNamespaceName($this->config->getNamespace()); $doc = new DocBlockGenerator(); $doc->setTag(new GenericTag('@service', $this->config->getWsdlDocumentPath())); $class->setDocBlock($doc); $this->serializeClass($class); return $class->getName(); }
/** * Determine the namespace of a type from the XMLSchema * * @param \Goetas\XML\XSDReader\Schema\Type\Type|\Sapone\Util\SimpleXMLElement $type * @return string */ public function inflectNamespace($type) { if ($type instanceof Type) { if ($type->getSchema()->getTargetNamespace() === SchemaReader::XSD_NS) { // XMLSchema primitive types do not have a namespace $namespace = null; } else { $namespace = array(); // prepend the base namespace if ($this->config->getNamespace()) { $namespace[] = $this->config->getNamespace(); } if ($this->config->isAxisNamespaces()) { // append the XMLSchema namespace, formatted in Apache Axis style $url = Url::createFromUrl($type->getSchema()->getTargetNamespace()); // the namespace is an url $namespace = array_merge($namespace, array_reverse(explode('.', $url->getHost()->get()))); if (!empty($url->getPath()->get())) { $namespace = array_merge($namespace, explode('/', $url->getPath()->get())); } } $namespace = implode('\\', $namespace); } return $namespace; } elseif ($type instanceof SimpleXMLElement) { if ($type->getNamespace() === SchemaReader::XSD_NS) { // XMLSchema primitive types do not have a namespace $namespace = null; } else { $namespace = array(); // prepend the base namespace if ($this->config->getNamespace()) { $namespace[] = $this->config->getNamespace(); } if ($this->config->isAxisNamespaces()) { // append the XMLSchema namespace, formatted in Apache Axis style $url = Url::createFromUrl($type->getNamespace()); // the namespace is an url $namespace = array_merge($namespace, array_reverse(explode('.', $url->getHost()->get()))); if (!empty($url->getPath()->get())) { $namespace = array_merge($namespace, explode('/', $url->getPath()->get())); } } $namespace = implode('\\', $namespace); } return $namespace; } else { throw new \InvalidArgumentException('Expected an instance of Goetas\\XML\\XSDReader\\Schema\\Type\\Type or Sapone\\Util\\SimpleXMLElement'); } }
/** * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { $config = new Config(); $config->setWsdlDocumentPath($input->getArgument('wsdl-path')); $config->setOutputPath($input->getArgument('output-path')); if ($input->getOption('namespace')) { $config->setNamespace($input->getOption('namespace')); } if ($input->getOption('axis-namespaces')) { $config->setAxisNamespaces($input->getOption('axis-namespaces')); } if ($input->getOption('autoloader')) { $config->setAutoloader($input->getOption('autoloader')); } if ($input->getOption('spl-enums')) { $config->setSplEnums(true); } if ($input->getOption('accessors')) { $config->setAccessors(true); } if ($input->getOption('null-constructor-arguments')) { $config->setNullConstructorArguments(true); } $generator = new Generator($config); $generator->getEventDispatcher()->addListener(Event::ENUM_CREATE, function (Event $event) use($output) { $output->writeln('<info> * </info>Enum class created: ' . $event->getClassName()); }); $generator->getEventDispatcher()->addListener(Event::DTO_CREATE, function (Event $event) use($output) { $output->writeln('<info> * </info>Data Transfer Object class created: ' . $event->getClassName()); }); $generator->getEventDispatcher()->addListener(Event::SERVICE_CREATE, function (Event $event) use($output) { $output->writeln('<info> * </info>Service class created: ' . $event->getClassName()); }); $generator->getEventDispatcher()->addListener(Event::CLASSMAP_CREATE, function (Event $event) use($output) { $output->writeln('<info> * </info>Classmap class created: ' . $event->getClassName()); }); $generator->generate(); }
public function testCodeGeneration() { $outputPath = __DIR__ . '/generated'; $config = new Config(); // wsdl document $config->setWsdlDocumentPath(__DIR__ . '/resources/service.wsdl'); // output path $config->setOutputPath($outputPath); // parameters $config->setNamespace('Sapone\\Test\\GeneratedCode'); $config->setAutoloader(Config::AUTOLOADER_PSR0); $config->setSplEnums(true); $config->setAccessors(true); // generate the code $generator = new Generator($config); $generator->generate(); // assert that the generated code is syntactically correct foreach (Finder::create()->in($outputPath)->name('*.php')->files() as $file) { $process = new Process(sprintf('php -l %s', escapeshellarg($file))); $process->run(); $this->assertTrue($process->isSuccessful()); } }
/** * Execute the code generation */ public function generate() { /* * PROXY CONFIGURATION */ $proxy = current(array_filter(array(getenv('HTTP_PROXY'), getenv('http_proxy')), 'strlen')); if ($proxy) { $parsedWsdlPath = Url::createFromUrl($this->config->getWsdlDocumentPath()); // if not fetching the wsdl file from filesystem and a proxy has been set if ($parsedWsdlPath->getScheme()->get() !== 'file') { $proxy = Url::createFromUrl($proxy); libxml_set_streams_context(stream_context_get_default(array($proxy->getScheme()->get() => array('proxy' => 'tcp://' . $proxy->getAuthority() . $proxy->getRelativeUrl(), 'request_fulluri' => true)))); } } unset($proxy); /* * LOAD THE WSDL DOCUMENT */ $wsdlDocument = SimpleXMLElement::loadFile($this->config->getWsdlDocumentPath()); $wsdlDocument->registerXPathNamespace('wsdl', static::WSDL_NS); $schemaReader = new SchemaReader(); /* @var \Goetas\XML\XSDReader\Schema\Schema[] $schemas */ $schemas = array(); /* @var \Goetas\XML\XSDReader\Schema\Type\Type[] $types */ $types = array(); /* * LOAD THE XML SCHEMAS */ // read the schemas included in the wsdl document foreach ($wsdlDocument->xpath('/wsdl:definitions/wsdl:types/xsd:schema') as $schemaNode) { $schemas[] = $schemaReader->readNode(dom_import_simplexml($schemaNode)); } // exclude the schemas having the following namespaces $unusedSchemaNamespaces = array(SchemaReader::XML_NS, SchemaReader::XSD_NS); // recursively read all the schema chain $processedSchemas = array(); while (!empty($schemas)) { /* @var \Goetas\XML\XSDReader\Schema\Schema $currentSchema */ $currentSchema = array_shift($schemas); if (!in_array($currentSchema, $processedSchemas) and !in_array($currentSchema->getTargetNamespace(), $unusedSchemaNamespaces)) { $processedSchemas[] = $currentSchema; $schemas = array_merge($schemas, $currentSchema->getSchemas()); } } $schemas = $processedSchemas; // cleanup unset($currentSchema); unset($processedSchemas); unset($unusedSchemaNamespaces); unset($schemaNode); unset($schemaReader); /* * LOAD THE DEFINED TYPES */ // get the complete list of defined types foreach ($schemas as $schema) { $types = array_merge($types, $schema->getTypes()); } /* * LOAD THE SERVICES */ $services = $wsdlDocument->xpath('/wsdl:definitions/wsdl:portType'); /* * CODE GENERATION */ $classFactory = new ClassFactory($this->config, $schemas, $types); foreach ($types as $type) { if ($type instanceof SimpleType) { // build the inheritance chain of the current SimpleType /* @var \Goetas\XML\XSDReader\Schema\Type\SimpleType[] $inheritanceChain */ $inheritanceChain = array($type->getRestriction()); // loop through the type inheritance chain untill the base type while (end($inheritanceChain) !== null) { $inheritanceChain[] = end($inheritanceChain)->getBase()->getParent(); } // remove the null value array_pop($inheritanceChain); // remove the 'anySimpleType' array_pop($inheritanceChain); // now the last element of the chain is the base simple type // enums are built only of string enumerations if (end($inheritanceChain)->getBase()->getName() === 'string' and array_key_exists('enumeration', $type->getRestriction()->getChecks())) { $className = $classFactory->createEnum($type); $this->eventDispatcher->dispatch(Event::ENUM_CREATE, new Event($className)); } } elseif ($type instanceof ComplexType) { $className = $classFactory->createDTO($type); $this->eventDispatcher->dispatch(Event::DTO_CREATE, new Event($className)); } } foreach ($services as $service) { $className = $classFactory->createService($service); $this->eventDispatcher->dispatch(Event::SERVICE_CREATE, new Event($className)); } $className = $classFactory->createClassmap(); $this->eventDispatcher->dispatch(Event::CLASSMAP_CREATE, new Event($className)); /* * GENERATED CODE FIX */ // create the coding standards fixer $fixer = new Fixer(); $config = new FixerConfig(); $config->setDir($this->config->getOutputPath()); // register all the existing fixers $fixer->registerBuiltInFixers(); $config->fixers(array_filter($fixer->getFixers(), function (FixerInterface $fixer) { return $fixer->getLevel() === FixerInterface::PSR2_LEVEL; })); // fix the generated code $fixer->fix($config); }