public function getPath(ClassGenerator $php) { foreach ($this->namespaces as $namespace => $dir) { if (strpos(trim($php->getNamespaceName()) . "\\", $namespace) === 0) { $d = strtr(substr($php->getNamespaceName(), strlen($namespace)), "\\", "/"); $dir = rtrim($dir, "/") . "/" . $d; if (!is_dir($dir) && !mkdir($dir, 0777, true)) { throw new PathGeneratorException("Can't create the '{$dir}' directory"); } return rtrim($dir, "/") . "/" . $php->getName() . ".php"; } } throw new PathGeneratorException("Can't find a defined location where save '{$php->getNamespaceName()}\\{$php->getName()}' object"); }
public function testNameAccessors() { $classGenerator = new ClassGenerator(); $classGenerator->setName('TestClass'); $this->assertEquals($classGenerator->getName(), 'TestClass'); }
/** * Write generated code to disk and return the class code * * {@inheritDoc} */ public function generate(ClassGenerator $classGenerator) { $className = trim($classGenerator->getNamespaceName(), '\\') . '\\' . trim($classGenerator->getName(), '\\'); $generatedCode = $classGenerator->generate(); $fileName = $this->fileLocator->getProxyFileName($className); $tmpFileName = $fileName . '.' . uniqid('', true); // renaming files is necessary to avoid race conditions when the same file is written multiple times // in a short time period file_put_contents($tmpFileName, "<?php\n\n" . $generatedCode); rename($tmpFileName, $fileName); return $generatedCode; }
/** * Write generated code to disk and return the class code * * {@inheritDoc} */ public function generate(ClassGenerator $classGenerator) { $className = trim($classGenerator->getNamespaceName(), '\\') . '\\' . trim($classGenerator->getName(), '\\'); $generatedCode = $classGenerator->generate(); $fileName = $this->fileLocator->getProxyFileName($className); set_error_handler($this->emptyErrorHandler); try { $this->writeFile("<?php\n\n" . $generatedCode, $fileName); } catch (FileNotWritableException $fileNotWritable) { restore_error_handler(); throw $fileNotWritable; } restore_error_handler(); return $generatedCode; }
/** * @param ClassGenerator $classGenerator * @return string * @throws FileNotWritableException */ public function generate(ClassGenerator $classGenerator) { $className = trim($classGenerator->getNamespaceName(), '\\') . '\\' . trim($classGenerator->getName(), '\\'); $generatedCode = $classGenerator->generate(); $fileName = $this->file->getProxyFileName($className); set_error_handler(function () { }); try { $this->write("<?php\n\n" . $generatedCode, $fileName); } catch (FileNotWritableException $exception) { throw $exception; } finally { restore_error_handler(); } return $fileName; }
/** * Generates a dynamic class implementing specified interfaces (and ServiceAwareInterface). * @return string class name */ public function build() { $generator = new ClassGenerator(uniqid('Proxy_'), 'SoPhp\\Rpc\\Proxy'); $generator->setImplementedInterfaces($this->getImplements()); $generator->setExtendedClass('\\SoPhp\\Rpc\\Proxy\\ProxyAbstract'); $source = $generator->generate(); $className = $generator->getNamespaceName() . '\\' . $generator->getName(); try { eval($source); } catch (\Exception $e) { throw new BuildFailed("Could not evaluate source code for proxy. " . $source, 0, $e); } if (!class_exists($className, false)) { throw new BuildFailed("Proxy class `{$className}` does not exist"); } return $className; }
/** * setClass() * * @param array|string|ClassGenerator $class * @return FileGenerator */ public function setClass($class) { if (is_array($class)) { $class = ClassGenerator::fromArray($class); $className = $class->getName(); } if (is_string($class)) { $class = new ClassGenerator($class); } if (!$class instanceof ClassGenerator) { throw new Exception\InvalidArgumentException('setClass() is expecting either a string, array or an instance of Zend\\Code\\Generator\\ClassGenerator'); } $className = $class->getName(); // @todo check for dup here $className = $class->getName(); $this->classes[$className] = $class; return $this; }
/** * Generate the code for the given className and primaryKey and write it in a file. * @param string $className The class name. * @param string $primaryKey The primary key. */ private function generateCode($className, $primaryKey) { $tags = $this->config->getTags(); $class = new ClassGenerator(); $docblock = DocBlockGenerator::fromArray(array('shortDescription' => ucfirst($className) . ' model class', 'longDescription' => 'This is a model class generated with DavidePastore\\ParisModelGenerator.', 'tags' => $tags)); $idColumn = new PropertyGenerator('_id_column'); $idColumn->setStatic(true)->setDefaultValue($primaryKey); $table = new PropertyGenerator('_table'); $table->setStatic(true)->setDefaultValue($className); $tableUseShortName = new PropertyGenerator('_table_use_short_name'); $tableUseShortName->setStatic(true)->setDefaultValue(true); $namespace = $this->config->getNamespace(); $extendedClass = '\\Model'; if (isset($namespace) && !empty($namespace)) { $class->setNamespaceName($this->config->getNamespace()); } $class->setName(ucfirst($className))->setDocblock($docblock)->setExtendedClass($extendedClass)->addProperties(array($idColumn, $table, $tableUseShortName)); $file = FileGenerator::fromArray(array('classes' => array($class), 'docblock' => DocBlockGenerator::fromArray(array('shortDescription' => ucfirst($className) . ' class file', 'longDescription' => null, 'tags' => $tags)))); $generatedCode = $file->generate(); $directory = $this->config->getDestinationFolder() . $namespace; if (!file_exists($directory)) { mkdir($directory, 0777, true); } $filePath = $directory . "/" . $class->getName() . ".php"; if (file_exists($filePath) && !$this->force) { $helper = $this->getHelper('question'); $realPath = realpath($filePath); $this->output->writeln("\n"); $question = new ConfirmationQuestion('Do you want to overwrite the file "' . $realPath . '"?', false); if ($helper->ask($this->input, $this->output, $question)) { $this->writeInFile($filePath, $generatedCode); } } else { $this->writeInFile($filePath, $generatedCode); } }
/** * Write a class to disk. * * @param ClassGenerator $classGenerator Representation of class to write * @param string $module Module in which to write class * @param bool $allowOverwrite Allow overwrite of existing file? * @param bool $skipBackup Should we skip backing up the file? * * @return void * @throws \Exception */ protected function writeClass(ClassGenerator $classGenerator, $module, $allowOverwrite = false, $skipBackup = false) { // Use the class name parts from the previous step to determine a path // and filename, then create the new path. $parts = explode('\\', $classGenerator->getNamespaceName()); array_unshift($parts, 'module', $module, 'src'); $this->createTree($parts); // Generate the new class: $generator = FileGenerator::fromArray(['classes' => [$classGenerator]]); $filename = $classGenerator->getName() . '.php'; $fullPath = APPLICATION_PATH . '/' . implode('/', $parts) . '/' . $filename; if (file_exists($fullPath)) { if ($allowOverwrite) { if (!$skipBackup) { $this->backUpFile($fullPath); } } else { throw new \Exception("{$fullPath} already exists."); } } if (!file_put_contents($fullPath, $generator->generate())) { throw new \Exception("Problem writing to {$fullPath}."); } Console::writeLine("Saved file: {$fullPath}"); }
/** * Fill file level phpdoc * * @param ClassGenerator $class contained class */ protected function defineFileInfo(ClassGenerator $class) { $doc = DocBlockGenerator::fromArray(array('shortDescription' => 'Contains ' . $class->getName() . ' class file', 'longDescription' => 'Generated Automatically.' . PHP_EOL . 'Please do not modify', 'tags' => array(array('name' => 'author', 'description' => $this->data['_author']), array('name' => 'license', 'description' => $this->data['_license']), array('name' => 'package', 'description' => $class->getNamespaceName())))); $this->fileGenerator->setDocBlock($doc); }
/** * Append methods to Api class * * @param Generator\ClassGenerator $class * @param string $operation * @param mixed $apiMetadata * @param FileGenerator $demoFile */ protected function generateApiOperationFromMetadata(Generator\ClassGenerator &$class, $httpMethod, $apiMetadata) { $console = $this->getServiceLocator()->get('console'); $modelClassName = 'Mailjet\\Model\\' . $class->getName(); $model = $class->getName(); $class->addUse('Zend\\Json\\Json')->addUse('Zend\\InputFilter'); $httpMethod = strtoupper($httpMethod); switch ($httpMethod) { case 'GET': if ($apiMetadata->Filters) { $class->addMethods(array(new Generator\MethodGenerator('getList', array(new Generator\ParameterGenerator('filters', 'array', array())), Generator\MethodGenerator::FLAG_PUBLIC, 'return parent::_list($filters);', new Generator\DocBlockGenerator("Return list of {$modelClassName}", "Return list of {$modelClassName} filtered by \$filters if provided" . PHP_EOL, array(new ParamTag(array('name' => 'filters', 'datatype' => 'array', 'description' => 'key/val filters')), new ReturnTag(array('datatype' => 'ResultSet\\ResultSet', 'description' => "List of {$modelClassName}"))))))); foreach ($apiMetadata->Filters as $filterInfo) { try { $filterName = $filterInfo->Name; $dataTypeInfos = $this->getNormalizedFilterOrProperty($filterInfo); $dataType = $dataTypeInfos['dataType']; foreach ($dataTypeInfos['uses'] as $use) { $class->addUse($use); } $isKey = $filterName == $apiMetadata->UniqueKey; if ($isKey) { $bodyMethod = sprintf('return $this->_get($%s);' . PHP_EOL, $filterName); } else { $bodyMethod = sprintf('$result = $this->getList(array(\'%s\' => $%s));' . PHP_EOL . 'return $result;', $filterName, $filterName); } $class->addMethods(array(new Generator\MethodGenerator('getBy' . $filterName, array(new Generator\ParameterGenerator($filterName, $dataType)), Generator\MethodGenerator::FLAG_PUBLIC, $bodyMethod, new Generator\DocBlockGenerator($isKey ? "Return {$modelClassName}" : "Return list of {$modelClassName} with {$filterName} = \${$filterName}", '', array(new ParamTag(array('name' => $filterName, 'datatype' => $dataType)), new ReturnTag(array('datatype' => $isKey ? $modelClassName : 'ResultSet\\ResultSet'))))))); } catch (\Exception $e) { $console->writeLine('[' . $class->getName() . ']' . $e->getMessage(), Color::YELLOW); } } $param = new Generator\ParameterGenerator('id', 'int'); $class->addMethods(array(new Generator\MethodGenerator('get', array($param), Generator\MethodGenerator::FLAG_PUBLIC, 'if (empty($id)) {' . PHP_EOL . ' throw new Exception\\InvalidArgumentException("You must specify the ID");' . PHP_EOL . '}' . PHP_EOL . PHP_EOL . 'return parent::_get($id);', new Generator\DocBlockGenerator("Return {$modelClassName} with id = \$id", '', array(new ParamTag(array('name' => 'id', 'datatype' => 'int', 'description' => 'Id of resource to get')), new ReturnTag(array('datatype' => $modelClassName))))))); } else { $class->addMethods(array(new Generator\MethodGenerator('current', array(), Generator\MethodGenerator::FLAG_PUBLIC, 'return parent::_get();', new Generator\DocBlockGenerator("Return current {$modelClassName}", '', array(new ReturnTag(array('datatype' => $modelClassName))))))); } break; case 'DELETE': $class->addMethods(array(new Generator\MethodGenerator('delete', array(new Generator\ParameterGenerator('id')), Generator\MethodGenerator::FLAG_PUBLIC, 'return parent::_delete($id);', new Generator\DocBlockGenerator("Delete the {$model} with id = \$id", '', array(new ParamTag(array('name' => 'id', 'datatype' => 'integer', 'description' => 'Id to delete')), new ReturnTag(array('datatype' => 'bool', 'description' => 'True on success'))))))); break; case 'POST': $modelParameter = new Generator\ParameterGenerator($model, $modelClassName); $modelParameter->setPassedByReference(true); $class->addMethods(array(new Generator\MethodGenerator('create', array($modelParameter), Generator\MethodGenerator::FLAG_PUBLIC, "return parent::_create(\${$model});", new Generator\DocBlockGenerator("Create a new {$model}", '', array(new ParamTag(array('name' => $model, 'datatype' => $modelClassName)), new ReturnTag(array('datatype' => "{$modelClassName}|false", 'description' => 'Object created or false'))))))); break; case 'PUT': $modelParameter = new Generator\ParameterGenerator($model, $modelClassName); $modelParameter->setPassedByReference(true); $class->addMethods(array(new Generator\MethodGenerator('update', array($modelParameter), Generator\MethodGenerator::FLAG_PUBLIC, "return parent::_update(\${$model});", new Generator\DocBlockGenerator("Update existing {$model}", '', array(new ParamTag(array('name' => $model, 'datatype' => $modelClassName)), new ReturnTag(array('datatype' => "{$modelClassName}|false", 'description' => 'Object created or false'))))))); break; default: break; } }
/** * Copied from ClassGenerator::fromReflection and tweaked slightly * @param ClassReflection $classReflection * * @return ClassGenerator */ public function getGeneratorFromReflection(ClassReflection $classReflection) { // class generator $cg = new ClassGenerator($classReflection->getName()); $cg->setSourceContent($cg->getSourceContent()); $cg->setSourceDirty(false); if ($classReflection->getDocComment() != '') { $docblock = DocBlockGenerator::fromReflection($classReflection->getDocBlock()); $docblock->setIndentation(Generator::$indentation); $cg->setDocBlock($docblock); } $cg->setAbstract($classReflection->isAbstract()); // set the namespace if ($classReflection->inNamespace()) { $cg->setNamespaceName($classReflection->getNamespaceName()); } /* @var \Zend\Code\Reflection\ClassReflection $parentClass */ $parentClass = $classReflection->getParentClass(); if ($parentClass) { $cg->setExtendedClass('\\' . ltrim($parentClass->getName(), '\\')); $interfaces = array_diff($classReflection->getInterfaces(), $parentClass->getInterfaces()); } else { $interfaces = $classReflection->getInterfaces(); } $interfaceNames = array(); foreach ($interfaces as $interface) { /* @var \Zend\Code\Reflection\ClassReflection $interface */ $interfaceNames[] = $interface->getName(); } $cg->setImplementedInterfaces($interfaceNames); $properties = array(); foreach ($classReflection->getProperties() as $reflectionProperty) { if ($reflectionProperty->getDeclaringClass()->getName() == $classReflection->getName()) { $property = PropertyGenerator::fromReflection($reflectionProperty); $property->setIndentation(Generator::$indentation); $properties[] = $property; } } $cg->addProperties($properties); $methods = array(); foreach ($classReflection->getMethods() as $reflectionMethod) { $className = $cg->getNamespaceName() ? $cg->getNamespaceName() . "\\" . $cg->getName() : $cg->getName(); if ($reflectionMethod->getDeclaringClass()->getName() == $className) { $method = MethodGenerator::fromReflection($reflectionMethod); $method->setBody(preg_replace("/^\\s+/m", '', $method->getBody())); $method->setIndentation(Generator::$indentation); $methods[] = $method; } } $cg->addMethods($methods); return $cg; }
/** * Serialize to disk the given class code * * @param \Zend\Code\Generator\ClassGenerator $class */ protected function serializeClass(ClassGenerator $class) { // serialize the class $fs = new Filesystem(); $file = new FileGenerator(array('class' => $class)); $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, $class->getNamespaceName()); } // append the file name $outputPath[] = $class->getName() . '.php'; // finalize the output path $outputPath = implode(DIRECTORY_SEPARATOR, $outputPath); $fs->mkdir(dirname($outputPath)); file_put_contents($outputPath, $file->generate()); }
/** * @param array|string|ClassGenerator $class * @throws Exception\InvalidArgumentException * @return FileGenerator */ public function setClass($class) { if (is_array($class)) { $class = ClassGenerator::fromArray($class); } elseif (is_string($class)) { $class = new ClassGenerator($class); } elseif (!$class instanceof ClassGenerator) { throw new Exception\InvalidArgumentException(sprintf('%s is expecting either a string, array or an instance of %s\\ClassGenerator', __METHOD__, __NAMESPACE__)); } // @todo check for dup here $className = $class->getName(); $this->classes[$className] = $class; return $this; }
/** * get setter methods for a parameter based on type * @param Generator\ClassGenerator $cg * @param string $name - the parameter name * @param int $type - The type of parameter to be handled * @param string $targetClass - the target class name to be set (only used in relational setters) * @return array $methods */ private function getSetterMethods(&$cg, $name, $type, $targetClass = null) { $methods = array(); switch ($type) { case self::PARAM_TYPE_ITEM: $method = new Generator\MethodGenerator(); $method->setDocBlock('@param string $' . $name); $method->setParameter(new ParameterGenerator($name)); $method->setBody('$this->' . $name . ' = $' . $name . ';'); $method->setName('set' . $this->camelCaseMethodName($name)); $methods[] = $method; break; case self::PARAM_TYPE_RELATION_SINGLE: $method = new Generator\MethodGenerator(); $method->setDocBlock('@param ' . $targetClass . ' $' . $name); $method->setParameter(new ParameterGenerator($name, $this->getTargetType($targetClass))); $method->setBody('$this->' . $name . ' = $' . $name . ';'); $method->setName('set' . $this->camelCaseMethodName($name)); $methods[] = $method; break; case self::PARAM_TYPE_RELATION_COLLECTION: $singledName = Inflector::singularize($name); $method = new Generator\MethodGenerator(); $method->setDocBlock('@param ' . $targetClass . ' $' . $singledName); $method->setParameter(new ParameterGenerator($singledName, $this->getTargetType($targetClass))); $method->setBody('$this->' . $name . '[] = $' . $singledName . ';'); $singleMethodName = 'add' . $this->camelCaseMethodName($singledName); $method->setName($singleMethodName); $methods[] = $method; $pluralName = Inflector::pluralize($name); if ($singledName === $pluralName) { // Unable to generate a pluralized collection method break; } $pluralMethod = new Generator\MethodGenerator(); $pluralMethod->setDocBlock('@param array $' . $name); $pluralMethod->setName('add' . $this->camelCaseMethodName($pluralName)); $pluralMethod->setParameter(new ParameterGenerator($pluralName, 'array')); $body = "foreach (\${$pluralName} as \${$singledName}) \n{\n"; $body .= " \$this->{$singleMethodName}(\${$singledName});\n}"; $pluralMethod->setBody($body); $methods[] = $pluralMethod; break; } // All setter methods will return $this for ($x = 0; $x < sizeof($methods); $x++) { /** @var Generator\MethodGenerator $methods [$x] * */ $docBlock = $methods[$x]->getDocBlock(); $docBlock->setShortDescription($docBlock->getShortDescription() . "\n@return " . $cg->getName() . ' $this'); $methods[$x]->setDocBlock($docBlock); $methods[$x]->setBody($methods[$x]->getBody() . "\nreturn \$this;"); } return $methods; }
/** * setClass() * * @param array|ClassGenerator $class * @return FileGenerator */ public function setClass(ClassGenerator $class) { /*if (is_array($class)) { $class = new ClassGenerator($class); $className = $class->getName(); } elseif ($class instanceof ClassGenerator) { $className = $class->getName(); } else { throw new Exception\InvalidArgumentException('Expecting either an array or an instance of Zend_CodeGenerator_Php_Class'); }*/ // @todo check for dup here $className = $class->getName(); $this->classes[$className] = $class; return $this; }
/** * Function writeClass. * * @param ClassGenerator $class * @param Filesystem $filesystem * @param $destinationDir * * @return string|false * * @throws CliException */ protected function writeClass(ClassGenerator $class, Filesystem $filesystem, $destinationDir) { $className = $class->getName(); $file = new FileGenerator(['fileName' => $className . '.php', 'classes' => [$class]]); $contents = $file->generate(); $relativePath = $destinationDir . DIRECTORY_SEPARATOR . $file->getFilename(); if ($filesystem->has($relativePath)) { throw new CliException(sprintf('Could not generate migration. File already exists: %s', $relativePath)); } $result = $filesystem->write($relativePath, $contents); return $result ? $relativePath : false; }