/** * @param Database $database */ public function generate(Database $database) { foreach ($database->getTables() as $table) { // Create namespace and inner class $namespace = new PhpNamespace($this->resolver->resolveRepositoryNamespace($table)); $class = $namespace->addClass($this->resolver->resolveRepositoryName($table)); // Detect extends class if (($extends = $this->config->get('repository.extends')) !== NULL) { $namespace->addUse($extends); $class->setExtends($extends); } // Save file $this->generateFile($this->resolver->resolveRepositoryFilename($table), (string) $namespace); } // Generate abstract base class if ($this->config->get('repository.extends') !== NULL) { // Create abstract class $namespace = new PhpNamespace($this->config->get('repository.namespace')); $class = $namespace->addClass(Helpers::extractShortName($this->config->get('repository.extends'))); $class->setAbstract(TRUE); // Add extends from ORM/Repository $extends = $this->config->get('nextras.orm.class.repository'); $namespace->addUse($extends); $class->setExtends($extends); // Save file $this->generateFile($this->resolver->resolveFilename(Helpers::extractShortName($this->config->get('repository.extends')), $this->config->get('repository.folder')), (string) $namespace); } }
/** * @return string PHP code */ public function __toString() { $parameters = array(); foreach ($this->parameters as $param) { $variadic = $this->variadic && $param === end($this->parameters); $hint = in_array($param->getTypeHint(), array('array', '')) ? $param->getTypeHint() : ($this->namespace ? $this->namespace->unresolveName($param->getTypeHint()) : $param->getTypeHint()); $parameters[] = ($hint ? $hint . ' ' : '') . ($param->isReference() ? '&' : '') . ($variadic ? '...' : '') . '$' . $param->getName() . ($param->isOptional() && !$variadic ? ' = ' . Helpers::dump($param->defaultValue) : ''); } $uses = array(); foreach ($this->uses as $param) { $uses[] = ($param->isReference() ? '&' : '') . '$' . $param->getName(); } return ($this->documents ? str_replace("\n", "\n * ", "/**\n" . implode("\n", (array) $this->documents)) . "\n */\n" : '') . ($this->abstract ? 'abstract ' : '') . ($this->final ? 'final ' : '') . ($this->visibility ? $this->visibility . ' ' : '') . ($this->static ? 'static ' : '') . 'function' . ($this->returnReference ? ' &' : '') . ($this->name ? ' ' . $this->name : '') . '(' . implode(', ', $parameters) . ')' . ($this->uses ? ' use (' . implode(', ', $uses) . ')' : '') . ($this->abstract || $this->body === FALSE ? ';' : ($this->name ? "\n" : ' ') . "{\n" . Nette\Utils\Strings::indent(trim($this->body), 1) . "\n}"); }
protected function execute(InputInterface $input, OutputInterface $output) { $config = $this->getApplication()->getConfig(); $dialog = $this->getHelper('dialog'); $className = $input->getArgument('className'); $modelName = $input->getArgument('modelName'); $endPoint = $input->getArgument('endPoint'); $model = $this->getModel($modelName); $buildDirectory = $config['build']['classes']; $buildPath = $buildDirectory . '/' . $className . '.php'; if (file_exists($buildPath)) { if (!$dialog->askConfirmation($output, sprintf('<question>Class file "%s" exists, overwrite?</question>', $buildPath), false)) { return; } } $modelConfig = ['properties' => $model->properties]; $configsDirectory = $config['build']['configs']; $configPath = realpath($configsDirectory . '/' . $modelName . '.json'); if (file_exists($configPath)) { $modelConfig = json_decode(file_get_contents($configPath), true); } $namespace = new PhpNamespace($config['namespace']); $namespace->addUse($config['extends']); $class = new ClassType($className, $namespace); $class->addExtend($config['extends']); if (!empty($endPoint)) { $class->addConst("ENDPOINT", $endPoint); } foreach ($model->properties as $propertyName => $propertyDef) { if (in_array($propertyName, $modelConfig['properties'], true)) { $property = $class->addProperty($propertyName)->setVisibility('public'); $accessorMethod = $class->addMethod($this->toCamelCase("get_" . $propertyName)); $accessorMethod->setBody('return $this->' . $propertyName . ';'); $mutatorMethod = $class->addMethod($this->toCamelCase("set_" . $propertyName)); $mutatorMethod->addParameter($propertyName); $mutatorMethod->setBody('$this->' . $propertyName . ' = $' . $propertyName . ';'); if (is_string($propertyDef['type'])) { $property->addDocument("@var {$propertyDef['type']}"); } else { $property->addDocument("@var mixed"); } } else { $output->writeln(sprintf("<info>Skipped property %s</info>", $propertyName)); } } file_put_contents($buildPath, str_replace("\t", " ", "<?php\n{$namespace}{$class}")); // TODO: replace with PHP_CodeSniffer library exec(sprintf('vendor/bin/phpcbf --standard=PSR2 --encoding=utf-8 "%s"', $buildPath)); $output->writeln(sprintf("<info>Class %s created</info>", $buildPath)); }
/** * @return string PHP code */ public function __toString() : string { $parameters = []; foreach ($this->parameters as $param) { $variadic = $this->variadic && $param === end($this->parameters); $hint = $this->namespace ? $this->namespace->unresolveName((string) $param->getTypeHint()) : $param->getTypeHint(); $parameters[] = ($hint ? $hint . ' ' : '') . ($param->isReference() ? '&' : '') . ($variadic ? '...' : '') . '$' . $param->getName() . ($param->isOptional() && !$variadic ? ' = ' . Helpers::dump($param->defaultValue) : ''); } $uses = []; foreach ($this->uses as $param) { $uses[] = ($param->isReference() ? '&' : '') . '$' . $param->getName(); } $returnType = $this->namespace ? $this->namespace->unresolveName((string) $this->returnType) : $this->returnType; return ($this->comment ? str_replace("\n", "\n * ", "/**\n" . $this->comment) . "\n */\n" : '') . ($this->abstract ? 'abstract ' : '') . ($this->final ? 'final ' : '') . ($this->visibility ? $this->visibility . ' ' : '') . ($this->static ? 'static ' : '') . 'function' . ($this->returnReference ? ' &' : '') . ' ' . $this->name . '(' . implode(', ', $parameters) . ')' . ($this->uses ? ' use (' . implode(', ', $uses) . ')' : '') . ($returnType ? ': ' . $returnType : '') . ($this->abstract || $this->body === FALSE ? ';' : ($this->name ? "\n" : ' ') . "{\n" . Nette\Utils\Strings::indent(ltrim(rtrim($this->body) . "\n"), 1) . '}'); }
/** * @return string PHP code */ public function __toString() { $consts = array(); foreach ($this->consts as $name => $value) { $consts[] = "const {$name} = " . Helpers::dump($value) . ";\n"; } $properties = array(); foreach ($this->properties as $property) { $doc = str_replace("\n", "\n * ", implode("\n", (array) $property->getDocuments())); $properties[] = ($property->getDocuments() ? strpos($doc, "\n") === FALSE ? "/** {$doc} */\n" : "/**\n * {$doc}\n */\n" : '') . $property->getVisibility() . ($property->isStatic() ? ' static' : '') . ' $' . $property->getName() . ($property->value === NULL ? '' : ' = ' . Helpers::dump($property->value)) . ";\n"; } $extends = $implements = $traits = array(); if ($this->namespace) { foreach ((array) $this->extends as $name) { $extends[] = $this->namespace->unresolveName($name); } foreach ((array) $this->implements as $name) { $implements[] = $this->namespace->unresolveName($name); } foreach ((array) $this->traits as $name) { $traits[] = $this->namespace->unresolveName($name); } } else { $extends = (array) $this->extends; $implements = (array) $this->implements; $traits = (array) $this->traits; } foreach ($this->methods as $method) { $method->setNamespace($this->namespace); } return Strings::normalize(($this->documents ? str_replace("\n", "\n * ", "/**\n" . implode("\n", (array) $this->documents)) . "\n */\n" : '') . ($this->abstract ? 'abstract ' : '') . ($this->final ? 'final ' : '') . $this->type . ' ' . $this->name . ' ' . ($this->extends ? 'extends ' . implode(', ', $extends) . ' ' : '') . ($this->implements ? 'implements ' . implode(', ', $implements) . ' ' : '') . "\n{\n\n" . Strings::indent(($this->traits ? 'use ' . implode(', ', $traits) . ";\n\n" : '') . ($this->consts ? implode('', $consts) . "\n\n" : '') . ($this->properties ? implode("\n", $properties) . "\n\n" : '') . implode("\n\n\n", $this->methods), 1) . "\n\n}") . "\n"; }
/** * @param string $className * @return string */ public function generate($className) { if (!class_exists($className)) { throw new InvalidArgumentException("Unknown class {$className}. Check for typos in class name and make sure" . " that given class is properly loaded."); } $origin = new ReflectionClass($className); $interface = ClassType::from(self::ACCESSOR_INTERFACE); $namespace = new PhpNamespace($this->naming->getNamespace()); $class = $namespace->addClass($this->naming->deriveClassName($className)); $class->addDocument("This class was automatically generated by Markatom/Accessor library."); $class->addImplement(self::ACCESSOR_INTERFACE); $class->addConst('TARGET', $origin->getName()); $class->addProperty('writer')->setVisibility('private'); $class->setMethods($interface->getMethods()); $class->getMethod('read')->setVisibility('public')->setBody($this->generateReadBody($origin)); $class->getMethod('write')->setVisibility('public')->setBody($this->generateWriteBody($origin)); return (string) $namespace; }
/** * @param Database $database */ public function generate(Database $database) { foreach ($database->getTables() as $table) { // Create namespace and inner class $namespace = new PhpNamespace($this->resolver->resolveEntityNamespace($table)); $class = $namespace->addClass($this->resolver->resolveEntityName($table)); // Detect extends class if (($extends = $this->config->get('entity.extends')) === NULL) { $extends = $this->config->get('nextras.orm.class.entity'); } // Add namespace and extends class $namespace->addUse($extends); $class->setExtends($extends); // Add table columns foreach ($table->getColumns() as $column) { if ($this->config->get('generator.entity.exclude.primary')) { if ($column->isPrimary()) { continue; } } foreach ($this->decorators as $decorator) { $decorator->doDecorate($column, $class, $namespace); } } // Save file $this->generateFile($this->resolver->resolveEntityFilename($table), (string) $namespace); } // Generate abstract base class if ($this->config->get('entity.extends') !== NULL) { // Create abstract class $namespace = new PhpNamespace($this->config->get('entity.namespace')); $class = $namespace->addClass(Helpers::extractShortName($this->config->get('entity.extends'))); $class->setAbstract(TRUE); // Add extends from ORM/Entity $extends = $this->config->get('nextras.orm.class.entity'); $namespace->addUse($extends); $class->setExtends($extends); // Save file $this->generateFile($this->resolver->resolveFilename(Helpers::extractShortName($this->config->get('entity.extends')), $this->config->get('entity.folder')), (string) $namespace); } }
/** * @param PhpNamespace $namespace * @param string $class_name * @param object $object */ public function object($namespace, $class_name, $object) { $class_name = ucfirst($class_name); $class = $namespace->addClass($class_name); $class->addDocument('Class ' . $class_name); foreach (get_object_vars($object) as $name => $value) { $property = $class->addProperty($name); $property->setVisibility('public'); switch (gettype($value)) { case 'object': $class_name = ucfirst($name); $property->addDocument('@var ' . $class_name . PHP_EOL); $this->object($namespace, $class_name, $value); break; case 'array': $type_doc = isset($value[0]) ? gettype($value[0]) . '[]' : 'array'; $property->addDocument('@var ' . $type_doc . PHP_EOL); break; default: $property->addDocument('@var ' . gettype($value) . PHP_EOL); } } }
/** * @param PhpNamespace $namespace * @param ClassType $class * @param Column $column * @return void */ public function doDecorate(Column $column, ClassType $class, PhpNamespace $namespace) { switch ($column->getType()) { // Map: DateTime case ColumnTypes::TYPE_DATETIME: $column->setType('DateTime'); if ($column->getDefault() !== NULL) { $column->setDefault('now'); } $namespace->addUse('Nette\\Utils\\DateTime'); break; // Map: Enum // Map: Enum case ColumnTypes::TYPE_ENUM: foreach ($column->getEnum() as $enum) { $name = Strings::upper($column->getName()) . '_' . $enum; $class->addConst($name, $enum); } if ($column->getDefault() !== NULL) { $column->setDefault(Strings::upper($column->getName()) . '_' . $column->getDefault()); } break; } }
/** * @param Table $table * @param PhpNamespace $namespace * @return mixed */ protected function getRealUse(Table $table, PhpNamespace $namespace) { $use = $namespace->unresolveName($this->resolver->resolveEntityNamespace($table) . Helpers::NS . $this->resolver->resolveEntityName($table)); if (Strings::compare($use, $table->getName())) { return NULL; } return $use; }
private function writeGeneratedCode(Code\PhpFile $file, Code\PhpNamespace $namespace) { $builder = $this->getContainerBuilder(); if (!is_dir($tempDir = $builder->expand('%tempDir%/cache/_Kdyby.Aop'))) { mkdir($tempDir, 0777, TRUE); } $key = md5(serialize($builder->parameters) . serialize(array_keys($namespace->getClasses()))); file_put_contents($cached = $tempDir . '/' . $key . '.php', (string) $file); return $cached; }
/** * */ public function build() { foreach ($this->metaDataFactory->getAllMetaData() as $meta_data) { $class_name = $meta_data->getName(); $space_name = $this->parseNamespace($class_name); printf('Generated classes related to %s\\%s' . PHP_EOL, $space_name, $class_name); $base_space = new PhpNamespace(ltrim($space_name . '\\' . $this->baseNamespace, '\\')); $base_class = $base_space->addClass($class_name); $constructor = $base_class->addMethod('__construct')->setVisibility("public")->addComment("Instantiate a new " . $base_class->getName()); if ($this->entityParent) { $base_space->addUse($this->entityParent); $base_class->setExtends($this->entityParent); } $base_space->addUse('Doctrine\\Common\\Collections\\ArrayCollection'); foreach ($meta_data->getFieldNames() as $field) { $type = $this->translateType($meta_data->getTypeOfField($field)); $base_class->addProperty($field)->setVisibility("protected")->addComment("")->addComment("@access protected")->addComment("@var {$type}"); $base_class->addMethod('get' . ucfirst($field))->setVisibility("public")->addComment("Get the value of {$field}")->addComment("")->addComment("@access public")->addComment("@return {$type} The value of {$field}")->addBody("return \$this->{$field};"); $base_class->addMethod('set' . ucfirst($field))->setVisibility("public")->addComment("Set the value of {$field}")->addComment("")->addComment("@access public")->addComment("@param {$type} \$value The value to set to {$field}")->addComment("@return " . $base_class->getName() . " The object instance for method chaining")->addBody("\$this->{$field} = \$value;")->addBody("")->addBody("return \$this;")->addParameter("value"); } foreach ($meta_data->getAssociationMappings() as $mapping) { $field = $mapping['fieldName']; $type = in_array($mapping['type'], $this->toOneTypes) ? $mapping['targetEntity'] : 'ArrayCollection'; $base_class->addProperty($field)->setVisibility("protected")->addComment("")->addComment("@access protected")->addComment("@var {$type}"); $base_class->addMethod('get' . ucfirst($field))->setVisibility("public")->addComment("Get the value of {$field}")->addComment("")->addComment("@access public")->addComment("@return {$type} The value of {$field}")->addBody("return \$this->{$field};"); if ($type == 'ArrayCollection') { $constructor->addBody("\$this->{$field} = new ArrayCollection();"); // // hasRelatedEntities() // addRelatedEntities() // removeRelatedEntities() // } else { // // hasRelatedEntity() // // On set, if value is set to null, check if bi-directional and remove // $parameter = $base_class->addMethod('set' . ucfirst($field))->setVisibility("public")->addComment("Set the value of {$field}")->addComment("")->addComment("@access public")->addComment("@param {$type} \$value The value to set to {$field}")->addComment("@return " . $base_class->getName() . " The object instance for method chaining")->addBody("\$this->{$field} = \$value;")->addBody("")->addBody("return \$this;")->addParameter("value")->setTypeHint($type); if ($mapping['inversedBy']) { $inverse = $this->metaDataFactory->getMetadataFor($mapping['targetEntity'])->getAssociationMapping($mapping['inversedBy']); if ($inverse['orphanRemoval']) { $parameter->setOptional(TRUE); } } if (isset($mapping['joinColumns'][0]['nullable']) && $mapping['joinColumns'][0]['nullable']) { $parameter->setOptional(TRUE); } } } $this->sortMethods($base_class); $this->sortProperties($base_class); $this->write($this->entityRoot, $base_space, $base_class, TRUE); $space = new PhpNamespace($space_name); $class = $space->addClass($class_name)->setExtends(ltrim($space_name . '\\' . $this->baseNamespace . '\\' . $class_name, '\\')); $class->addMethod('__construct')->setVisibility("public")->addComment("Instantiate a new " . $class->getName())->addBody("return parent::__construct();"); $this->write($this->entityRoot, $space, $class); if ($meta_data->customRepositoryClassName) { $repo_class_name = $meta_data->customRepositoryClassName; $repo_space_name = $this->parseNamespace($repo_class_name); $repo_space = new PhpNamespace($repo_space_name); $repo_class = $repo_space->addClass($repo_class_name); $repo_space->addUse($this->repositoryParent); $repo_class->setExtends($this->repositoryParent); $this->write($this->repositoryRoot, $repo_space, $repo_class); } } }
/** * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { $root_class = $this->app['engine']->fetch('doctrine/entities', 'root_class'); $base_namespace = $this->app['engine']->fetch('doctrine/entities', 'base_namespace'); $entity_root = $this->app['engine']->fetch('doctrine/entities', 'entity_root'); $entity_root = $this->app->getDirectory($entity_root); $repo_root = $this->app['engine']->fetch('doctrine/entities', 'repository_root'); $repo_root = $this->app->getDirectory($repo_root); foreach ($this->metaData as $meta_data) { $class_name = $meta_data->getName(); $space_name = $this->parseNamespace($class_name); printf('Generated classes related to %s\\%s', $space_name, $class_name); $base_space = new PhpNamespace(ltrim($space_name . '\\' . $base_namespace, '\\')); $base_class = $base_space->addClass($class_name); $constructor = $base_class->addMethod('__construct')->setVisibility("public")->addComment("Instantiate a new " . $base_class->getName()); if ($root_class) { $base_space->addUse($root_class); $base_class->setExtends($root_class); } $base_space->setBracketedSyntax(TRUE); $base_space->addUse('Doctrine\\Common\\Collections\\ArrayCollection'); foreach ($meta_data->getFieldNames() as $field) { $type = $this->translateType($meta_data->getTypeOfField($field)); $base_class->addProperty($field)->setVisibility("protected")->addComment("")->addComment("@access protected")->addComment("@var {$type}"); $base_class->addMethod('get' . ucfirst($field))->setVisibility("public")->addComment("Get the value of {$field}")->addComment("")->addComment("@access public")->addComment("@return {$type} The value of {$field}")->addBody("return \$this->{$field};"); $base_class->addMethod('set' . ucfirst($field))->setVisibility("public")->addComment("Set the value of {$field}")->addComment("")->addComment("@access public")->addComment("@param {$type} \$value The value to set to {$field}")->addComment("@return " . $base_class->getName() . " The object instance for method chaining")->addBody("\$this->{$field} = \$value;")->addBody("")->addBody("return \$this;")->addParameter("value"); } foreach ($meta_data->getAssociationMappings() as $mapping) { $field = $mapping['fieldName']; $type = in_array($mapping['type'], $this->toOneTypes) ? $mapping['targetEntity'] : 'ArrayCollection'; $base_class->addProperty($field)->setVisibility("protected")->addComment("")->addComment("@access protected")->addComment("@var {$type}"); $base_class->addMethod('get' . ucfirst($field))->setVisibility("public")->addComment("Get the value of {$field}")->addComment("")->addComment("@access public")->addComment("@return {$type} The value of {$field}")->addBody("return \$this->{$field};"); if ($type == 'ArrayCollection') { $constructor->addBody("\$this->{$field} = new ArrayCollection();"); // // hasRelatedEntities() // addRelatedEntities() // removeRelatedEntities() // } else { // // hasRelatedEntity() // // On set, if value is set to null, check if bi-directional and remove // $base_class->addMethod('set' . ucfirst($field))->setVisibility("public")->addComment("Set the value of {$field}")->addComment("")->addComment("@access public")->addComment("@param {$type} \$value The value to set to {$field}")->addComment("@return " . $base_class->getName() . " The object instance for method chaining")->addBody("\$this->{$field} = \$value;")->addBody("")->addBody("return \$this;")->addParameter("value")->setTypeHint($type); } } $this->sortMethods($base_class); $this->sortProperties($base_class); $this->write($entity_root, $base_space, $base_class, TRUE); $space = new PhpNamespace($space_name); $class = $space->addClass($class_name)->setExtends($space_name . '\\' . $base_namespace . '\\' . $class_name); $class->addMethod('__construct')->setVisibility("public")->addComment("Instantiate a new " . $class->getName())->addBody("return parent::__construct();"); $space->setBracketedSyntax(TRUE); $this->write($entity_root, $space, $class); if ($meta_data->customRepositoryClassName) { $repo_class_name = $meta_data->customRepositoryClassName; $repo_space_name = $this->parseNamespace($repo_class_name); $repo_space = new PhpNamespace($repo_space_name); $repo_class = $repo_space->addClass($repo_class_name); $repo_space->setBracketedSyntax(TRUE); $repo_space->addUse('Inkwell\\Doctrine\\Repository'); $repo_class->setExtends('Inkwell\\Doctrine\\Repository'); $this->write($repo_root, $repo_space, $repo_class); } echo PHP_EOL; } }