/**
  * @param \Protobuf\Stream $stream
  *
  * @return \Protobuf\Stream
  */
 public function compile(Stream $stream)
 {
     // Parse the request
     $request = CodeGeneratorRequest::fromStream($stream, $this->config);
     $response = new CodeGeneratorResponse();
     $context = $this->createContext($request);
     $entities = $context->getEntities();
     $options = $context->getOptions();
     $generator = new Generator($context);
     // whether or not it will renegerate classes with new extensions
     $regenerate = false;
     $hasExtension = $context->hasProtobufExtension();
     // Run each entity
     foreach ($entities as $key => $entity) {
         $generateImported = $options->getGenerateImported();
         $isFileToGenerate = $entity->isFileToGenerate();
         // Only compile those given to generate, not the imported ones
         if (!$generateImported && !$isFileToGenerate) {
             $this->logger->debug(sprintf('Skipping generation of imported class "%s"', $entity->getClass()));
             continue;
         }
         $this->logger->info(sprintf('Generating class "%s"', $entity->getClass()));
         $generator->visit($entity);
         $file = new File();
         $path = $entity->getPath();
         $content = $entity->getContent();
         $file->setName($path);
         $file->setContent($content);
         $response->addFile($file);
         if ($hasExtension && $this->loadEntityClass($entity)) {
             $regenerate = true;
         }
     }
     if ($regenerate) {
         $this->logger->info('Regenerating classes with new extensions');
         $stream->seek(0);
         // Renegerate classes with new extensions
         return $this->compile($stream);
     }
     $this->logger->info('Generation completed.');
     // Finally serialize the response object
     return $response->toStream($this->config);
 }
 public function testGenerateSimpleMessage()
 {
     $binaryRequest = $this->getFixtureFileContent('compiler/generator-request-simple.bin');
     $expectedContent = $this->getFixtureFileContent('Simple.tpl');
     $compiler = new Compiler($this->logger);
     $binaryResponse = $compiler->compile(Stream::wrap($binaryRequest));
     $response = CodeGeneratorResponse::fromStream($binaryResponse);
     $this->assertInstanceOf('google\\protobuf\\compiler\\CodeGeneratorResponse', $response);
     $this->assertInstanceOf('Protobuf\\Collection', $response->getFileList());
     $this->assertCount(1, $response->getFileList());
     $file = $response->getFileList()[0];
     $this->assertInstanceOf('google\\protobuf\\compiler\\CodeGeneratorResponse\\File', $file);
     $this->assertEquals('ProtobufCompilerTest/Protos/Simple.php', $file->getName());
     $this->assertEquals($expectedContent, $file->getContent());
 }
Exemple #3
0
 public function handle(CodeGeneratorRequest $request)
 {
     $files = array();
     foreach ((array) $request->getProtoFile() as $file) {
         /** @var FileDescriptorProto $file */
         $this->collectFile($file, array());
         $specClassName = "Skrz\\Meta\\MetaSpec";
         $customSpecClassName = false;
         foreach ($file->getSourceCodeInfo()->getLocation() as $location) {
             if ($location->getPath() === array(FileDescriptorProtoMeta::PACKAGE_PROTOBUF_FIELD) && $location->getLeadingComments() && preg_match("/@spec\\s+([a-zA-Z0-9_\\\\]+)/", $location->getLeadingComments(), $m)) {
                 $specClassName = $m[1];
                 $customSpecClassName = true;
             }
         }
         uksort($this->messages, function ($a, $b) {
             if (strlen($a) === strlen($b)) {
                 return strcmp($b, $a);
             }
             return strlen($b) - strlen($a);
         });
         $tmpFiles = array();
         foreach ($this->messages as $className => $message) {
             // compile message file
             $codeFile = new CodeGeneratorResponse\File();
             $codeFile->setName(str_replace("\\", "/", $className) . ".php");
             $result = $this->generateMessage($className, $message);
             $codeFile->setContent((string) $result->getFile());
             $files[$className] = $codeFile;
             // compile meta file
             if (!class_exists($className)) {
                 $tmpFiles[] = $tmpFile = tempnam(sys_get_temp_dir(), "protoc-gen-php");
                 file_put_contents($tmpFile, (string) $result->getFile());
                 require_once $tmpFile;
             }
             /** @var AbstractMetaSpec $spec */
             $spec = new $specClassName();
             if (!$customSpecClassName) {
                 $spec->match($className)->addModule(new ProtobufModule());
             }
             $metaResult = $spec->compile($type = Type::fromString($className));
             if ($metaResult !== null) {
                 $metaFile = new CodeGeneratorResponse\File();
                 $metaFile->setName(str_replace("\\", "/", $spec->createMetaClassName($type)) . ".php");
                 $metaFile->setContent((string) $metaResult->getFile());
                 $files[$metaResult->getClass()->getName()] = $metaFile;
             }
         }
         foreach ($tmpFiles as $tmpFile) {
             unlink($tmpFile);
         }
         foreach ($this->enums as $className => $enum) {
             $enumFile = new CodeGeneratorResponse\File();
             $enumFile->setName(str_replace("\\", "/", $className) . ".php");
             $result = $this->generateEnum($className, $enum);
             $enumFile->setContent((string) $result->getFile());
             $files[$className] = $enumFile;
         }
     }
     $response = new CodeGeneratorResponse();
     $response->setFile($files);
     return $response;
 }