diff --git a/lib/Doctrine/Common/Cli/CliController.php b/lib/Doctrine/Common/Cli/CliController.php index c91e6941e..067587fc9 100644 --- a/lib/Doctrine/Common/Cli/CliController.php +++ b/lib/Doctrine/Common/Cli/CliController.php @@ -83,7 +83,8 @@ class CliController extends AbstractNamespace ->addTask('run-dql', $ns . '\RunDqlTask') ->addTask('schema-tool', $ns . '\SchemaToolTask') ->addTask('version', $ns . '\VersionTask') - ->addTask('convert-d1-schema', $ns . '\ConvertDoctrine1SchemaTask'); + ->addTask('convert-d1-schema', $ns . '\ConvertDoctrine1SchemaTask') + ->addTask('generate-entity-stubs', $ns . '\GenerateEntityStubsTask'); $ns = 'Doctrine\DBAL\Tools\Cli\Tasks'; $this->addNamespace('Dbal') diff --git a/lib/Doctrine/ORM/Tools/Cli/Tasks/ConvertMappingTask.php b/lib/Doctrine/ORM/Tools/Cli/Tasks/ConvertMappingTask.php index 6e6e3ab7f..fb5eda3ca 100644 --- a/lib/Doctrine/ORM/Tools/Cli/Tasks/ConvertMappingTask.php +++ b/lib/Doctrine/ORM/Tools/Cli/Tasks/ConvertMappingTask.php @@ -171,7 +171,7 @@ class ConvertMappingTask extends AbstractTask $exporter->export(); } - private function _determineSourceType($source) + protected function _determineSourceType($source) { // If the --from= is a directory lets determine if it is // annotations, yaml, xml, etc. @@ -204,7 +204,7 @@ class ConvertMappingTask extends AbstractTask } } - private function _getSourceByType($type, $source) + protected function _getSourceByType($type, $source) { // If --from==database then the source is an instance of SchemaManager // for the current EntityMAnager diff --git a/lib/Doctrine/ORM/Tools/Cli/Tasks/GenerateEntityStubsTask.php b/lib/Doctrine/ORM/Tools/Cli/Tasks/GenerateEntityStubsTask.php new file mode 100644 index 000000000..ea5712b2a --- /dev/null +++ b/lib/Doctrine/ORM/Tools/Cli/Tasks/GenerateEntityStubsTask.php @@ -0,0 +1,123 @@ +. + */ + +namespace Doctrine\ORM\Tools\Cli\Tasks; + +use Doctrine\Common\Cli\Tasks\AbstractTask, + Doctrine\Common\Cli\Option, + Doctrine\Common\Cli\OptionGroup, + Doctrine\Common\Cli\CliException, + Doctrine\ORM\Tools\EntityGenerator, + Doctrine\ORM\Tools\Export\ClassMetadataExporter; + +/** + * CLI Task to generate entity classes and method stubs from your mapping information. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class GenerateEntityStubsTask extends ConvertMappingTask +{ + /** + * @inheritdoc + */ + public function buildDocumentation() + { + $options = new OptionGroup(OptionGroup::CARDINALITY_N_N, array( + new Option('from', '', 'The path to mapping information.'), + new Option('dest', '', 'The path to your entities.') + )); + + $doc = $this->getDocumentation(); + $doc->setName('generate-entity-stubs') + ->setDescription('Generate entity classes and method stubs from your mapping information.') + ->getOptionGroup() + ->addOption($options); + } + + /** + * @inheritdoc + */ + public function validate() + { + $arguments = $this->getArguments(); + $em = $this->getConfiguration()->getAttribute('em'); + + if ( ! isset($arguments['from']) || ! isset($arguments['dest'])) { + throw new CliException('You must specify a value for --from and --dest'); + } + + return true; + } + + public function run() + { + $printer = $this->getPrinter(); + $arguments = $this->getArguments(); + $from = $arguments['from']; + $dest = realpath($arguments['dest']); + + $generator = new EntityGenerator(); + $generator->setGenerateAnnotations(true); + $generator->setGenerateStubMethods(true); + $generator->setRegenerateEntityIfExists(false); + $generator->setUpdateEntityIfExists(true); + + if (isset($arguments['extend']) && $arguments['extend']) { + $generator->setClassToExtend($arguments['extend']); + } + + if (isset($arguments['num-spaces']) && $arguments['extend']) { + $generator->setNumSpaces($arguments['num-spaces']); + } + + $type = $this->_determineSourceType($from); + + if ( ! $type) { + throw new CliException( + "Invalid mapping source type '$sourceArg'." + ); + } + + $source = $this->_getSourceByType($type, $from); + + $cme = new ClassMetadataExporter(); + $cme->addMappingSource($source, $type); + $metadatas = $cme->getMetadatasForMappingSources(); + + $printer->writeln( + sprintf( + 'Generating entity stubs for "%s" mapping information located at "%s" to "%s"', + $printer->format($type, 'KEYWORD'), + $printer->format($from, 'KEYWORD'), + $printer->format($dest, 'KEYWORD') + ) + ); + + $generator->generate($metadatas, $dest); + } +} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Tools/EntityGenerator.php b/lib/Doctrine/ORM/Tools/EntityGenerator.php new file mode 100644 index 000000000..50b980b1e --- /dev/null +++ b/lib/Doctrine/ORM/Tools/EntityGenerator.php @@ -0,0 +1,832 @@ +. + */ + +namespace Doctrine\ORM\Tools; + +use Doctrine\ORM\Mapping\ClassMetadataInfo, + Doctrine\ORM\Mapping\AssociationMapping; + +/** + * Generic class used to generate PHP5 entity classes from ClassMetadataInfo instances + * + * [php] + * $classes = $em->getClassMetadataFactory()->getAllMetadata(); + * + * $generator = new \Doctrine\ORM\Tools\EntityGenerator(); + * $generator->setGenerateAnnotations(true); + * $generator->setGenerateStubMethods(true); + * $generator->setRegenerateEntityIfExists(false); + * $generator->setUpdateEntityIfExists(true); + * $generator->generate($classes, '/path/to/generate/entities'); + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class EntityGenerator +{ + /** The extension to use for written php files */ + private $_extension = '.php'; + + /** Whether or not the current ClassMetadataInfo instance is new or old */ + private $_isNew; + + /** If $_isNew is false then current code contains the current code from disk */ + private $_currentCode; + + /** Number of spaces to use for indention in generated code */ + private $_numSpaces = 4; + + /** The actual spaces to use for indention */ + private $_spaces = ' '; + + /** The class all generated entities should extend */ + private $_classToExtend; + + /** Whether or not to generation annotations */ + private $_generateAnnotations = false; + + /** Whether or not to generated sub methods */ + private $_generateStubMethods = false; + + /** Whether or not to update the entity class if it exists already */ + private $_updateEntityIfExists = false; + + /** Whether or not to re-generate entity class if it exists already */ + private $_regenerateEntityIfExists = false; + + private static $_template = +' + + +{ + +}'; + + /** + * Generate and write entity classes for the given array of ClassMetadataInfo instances + * + * @param array $metadatas + * @param string $outputDirectory + * @return void + */ + public function generate(array $metadatas, $outputDirectory) + { + foreach ($metadatas as $metadata) { + $this->writeEntityClass($metadata, $outputDirectory); + } + } + + /** + * Generated and write entity class to disk for the given ClassMetadataInfo instance + * + * @param ClassMetadataInfo $metadata + * @param string $outputDirectory + * @return void + */ + public function writeEntityClass(ClassMetadataInfo $metadata, $outputDirectory) + { + $path = $outputDirectory . '/' . str_replace('\\', DIRECTORY_SEPARATOR, $metadata->name) . $this->_extension; + $dir = dirname($path); + if ( ! is_dir($dir)) { + mkdir($dir, 0777, true); + } + + $this->_isNew = ! file_exists($path); + + // If entity doesn't exist or we're re-generating the entities entirely + if ($this->_isNew || ( ! $this->_isNew && $this->_regenerateEntityIfExists)) { + file_put_contents($path, $this->generateEntityClass($metadata)); + + // If entity exists and we're allowed to update the entity class + } else if ( ! $this->_isNew && $this->_updateEntityIfExists) { + file_put_contents($path, $this->generateUpdatedEntityClass($metadata, $path)); + } + } + + /** + * Generate a PHP5 Doctrine 2 entity class from the given ClassMetadataInfo instance + * + * @param ClassMetadataInfo $metadata + * @return string $code + */ + public function generateEntityClass(ClassMetadataInfo $metadata) + { + $placeHolders = array( + '', + '', + '', + '', + '' + ); + + $replacements = array( + $this->_generateEntityNamespace($metadata), + $this->_generateEntityUse($metadata), + $this->_generateAnnotations ? "\n" . $this->_generateEntityAnnotation($metadata) : null, + $this->_generateEntityClassName($metadata), + $this->_generateEntityBody($metadata) + ); + + $code = str_replace($placeHolders, $replacements, self::$_template); + return $code; + } + + /** + * Generate the updated code for the given ClassMetadataInfo and entity at path + * + * @param ClassMetadataInfo $metadata + * @param string $path + * @return string $code; + */ + public function generateUpdatedEntityClass(ClassMetadataInfo $metadata, $path) + { + $this->_currentCode = file_get_contents($path); + + $body = $this->_generateEntityBody($metadata); + + $last = strrpos($this->_currentCode, '}'); + $code = substr($this->_currentCode, 0, $last) . $body . '}'; + return $code; + } + + /** + * Set the number of spaces the exported class should have + * + * @param integer $numSpaces + * @return void + */ + public function setNumSpaces($numSpaces) + { + $this->_spaces = str_repeat(' ', $numSpaces); + $this->_numSpaces = $numSpaces; + } + + /** + * Set the extension to use when writing php files to disk + * + * @param string $extension + * @return void + */ + public function setExtension($extension) + { + $this->_extension = $extension; + } + + /** + * Set the name of the class the generated classes should extend from + * + * @return void + */ + public function setClassToExtend($classToExtend) + { + $this->_classToExtend = $classToExtend; + } + + /** + * Set whether or not to generate annotations for the entity + * + * @param bool $bool + * @return void + */ + public function setGenerateAnnotations($bool) + { + $this->_generateAnnotations = $bool; + } + + /** + * Set whether or not to try and update the entity if it already exists + * + * @param bool $bool + * @return void + */ + public function setUpdateEntityIfExists($bool) + { + $this->_updateEntityIfExists = $bool; + } + + /** + * Set whether or not to regenerate the entity if it exists + * + * @param bool $bool + * @return void + */ + public function setRegenerateEntityIfExists($bool) + { + $this->_regenerateEntityIfExists = $bool; + } + + /** + * Set whether or not to generate stub methods for the entity + * + * @param bool $bool + * @return void + */ + public function setGenerateStubMethods($bool) + { + $this->_generateStubMethods = $bool; + } + + private function _generateEntityNamespace(ClassMetadataInfo $metadata) + { + if ($this->_hasNamespace($metadata)) { + return 'namespace ' . $this->_getNamespace($metadata) .';'; + } + } + + private function _generateEntityUse(ClassMetadataInfo $metadata) + { + if ($this->_extendsClass()) { + return "\n\nuse " . $this->_getClassToExtendNamespace().";\n"; + } + } + + private function _generateEntityClassName(ClassMetadataInfo $metadata) + { + return 'class ' . $this->_getClassName($metadata) . + ($this->_extendsClass() ? 'extends ' . $this->_getClassToExtendName() : null); + } + + private function _generateEntityBody(ClassMetadataInfo $metadata) + { + $fieldMappingProperties = $this->_generateEntityFieldMappingProperties($metadata); + $associationMappingProperties = $this->_generateEntityAssociationMappingProperties($metadata); + $stubMethods = $this->_generateStubMethods ? $this->_generateEntityStubMethods($metadata) : null; + $lifecycleCallbackMethods = $this->_generateEntityLifecycleCallbackMethods($metadata); + + $code = ''; + if ($fieldMappingProperties) { + $code .= $fieldMappingProperties . "\n"; + } + if ($associationMappingProperties) { + $code .= $associationMappingProperties . "\n"; + } + if ($stubMethods) { + $code .= $stubMethods . "\n"; + } + if ($lifecycleCallbackMethods) { + $code .= $lifecycleCallbackMethods . "\n"; + } + return $code; + } + + private function _hasProperty($property, $metadata) + { + if ($this->_isNew) { + return false; + } else { + return strpos($this->_currentCode, '$' . $property) !== false ? true : false; + } + } + + private function _hasMethod($method, $metadata) + { + if ($this->_isNew) { + return false; + } else { + return strpos($this->_currentCode, 'function ' . $method) !== false ? true : false; + } + } + + private function _hasNamespace($metadata) + { + return strpos($metadata->name, '\\') ? true : false; + } + + private function _extendsClass() + { + return $this->_classToExtend ? true : false; + } + + private function _getClassToExtend() + { + return $this->_classToExtend; + } + + private function _getClassToExtendName() + { + $refl = new \ReflectionClass($this->_getClassToExtend()); + return $refl->getShortName(); + } + + private function _getClassToExtendNamespace() + { + $refl = new \ReflectionClass($this->_getClassToExtend()); + return $refl->getNamespaceName() ? $refl->getNamespaceName():$refl->getShortName(); + } + + private function _getClassName($metadata) + { + if ($pos = strrpos($metadata->name, '\\')) { + return substr($metadata->name, $pos + 1, strlen($metadata->name)); + } else { + return $metadata->name; + } + } + + private function _getNamespace($metadata) + { + return substr($metadata->name, 0, strrpos($metadata->name, '\\')); + } + + private function _generateEntityAnnotation($metadata) + { + $lines = array(); + $lines[] = '/**'; + + $methods = array( + '_generateTableAnnotation', + '_generateInheritanceAnnotation', + '_generateDiscriminatorColumnAnnotation', + '_generateDiscriminatorMapAnnotation' + ); + + foreach ($methods as $method) { + if ($code = $this->$method($metadata)) { + $lines[] = ' * ' . $code; + } + } + + if ($metadata->isMappedSuperclass) { + $lines[] = ' * @MappedSupperClass'; + } else { + $lines[] = ' * @Entity'; + } + + if ($metadata->customRepositoryClassName) { + $lines[count($lines) - 1] .= '(repositoryClass="' . $metadata->customRepositoryClassName . '")'; + } + + if (isset($metadata->lifecycleCallbacks) && $metadata->lifecycleCallbacks) { + $lines[] = ' * @HasLifecycleCallbacks'; + } + + $lines[] = ' */'; + + return implode("\n", $lines); + } + + private function _generateTableAnnotation($metadata) + { + $table = array(); + $table[] = 'name="' . $metadata->primaryTable['name'] . '"'; + + if (isset($metadata->primaryTable['schema'])) { + $table[] = 'schema="' . $metadata->primaryTable['schema'] . '"'; + } + + return '@Table(' . implode(', ', $table) . ')'; + } + + private function _generateInheritanceAnnotation($metadata) + { + if ($metadata->inheritanceType != ClassMetadataInfo::INHERITANCE_TYPE_NONE) { + return '@InheritanceType("'.$this->_getInheritanceTypeString($metadata->inheritanceType).'")'; + } + } + + private function _generateDiscriminatorColumnAnnotation($metadata) + { + if ($metadata->inheritanceType != ClassMetadataInfo::INHERITANCE_TYPE_NONE) { + $discrColumn = $metadata->discriminatorValue; + $columnDefinition = 'name="' . $discrColumn['name'] + . '", type="' . $discrColumn['type'] + . '", length=' . $discrColumn['length']; + + return '@DiscriminatorColumn(' . $columnDefinition . ')'; + } + } + + private function _generateDiscriminatorMapAnnotation($metadata) + { + if ($metadata->inheritanceType != ClassMetadataInfo::INHERITANCE_TYPE_NONE) { + $inheritanceClassMap = array(); + + foreach ($metadata->discriminatorMap as $type => $class) { + $inheritanceClassMap[] .= '"' . $type . '" = "' . $class . '"'; + } + + return '@DiscriminatorMap({' . implode(', ', $inheritanceClassMap) . '})'; + } + } + + private function _generateEntityStubMethods(ClassMetadataInfo $metadata) + { + $methods = array(); + + foreach ($metadata->fieldMappings as $fieldMapping) { + if ( ! isset($fieldMapping['id']) || ! $fieldMapping['id']) { + if ($code = $this->_generateStubMethod('set', $fieldMapping['fieldName'], $metadata)) { + $methods[] = $code; + } + } + + if ($code = $this->_generateStubMethod('get', $fieldMapping['fieldName'], $metadata)) { + $methods[] = $code; + } + } + + foreach ($metadata->associationMappings as $associationMapping) { + if ($associationMapping instanceof \Doctrine\ORM\Mapping\OneToOneMapping) { + if ($code = $this->_generateStubMethod('set', $associationMapping->sourceFieldName, $metadata)) { + $methods[] = $code; + } + if ($code = $this->_generateStubMethod('get', $associationMapping->sourceFieldName, $metadata)) { + $methods[] = $code; + } + } else if ($associationMapping instanceof \Doctrine\ORM\Mapping\OneToManyMapping) { + if ($associationMapping->isOwningSide) { + if ($code = $this->_generateStubMethod('set', $associationMapping->sourceFieldName, $metadata)) { + $methods[] = $code; + } + if ($code = $this->_generateStubMethod('get', $associationMapping->sourceFieldName, $metadata)) { + $methods[] = $code; + } + } else { + if ($code = $this->_generateStubMethod('add', $associationMapping->sourceFieldName, $metadata)) { + $methods[] = $code; + } + if ($code = $this->_generateStubMethod('get', $associationMapping->sourceFieldName, $metadata)) { + $methods[] = $code; + } + } + } else if ($associationMapping instanceof \Doctrine\ORM\Mapping\ManyToManyMapping) { + if ($code = $this->_generateStubMethod('add', $associationMapping->sourceFieldName, $metadata)) { + $methods[] = $code; + } + if ($code = $this->_generateStubMethod('get', $associationMapping->sourceFieldName, $metadata)) { + $methods[] = $code; + } + } + } + + return implode('', $methods); + } + + private function _generateEntityLifecycleCallbackMethods(ClassMetadataInfo $metadata) + { + if (isset($metadata->lifecycleCallbacks) && $metadata->lifecycleCallbacks) { + $methods = array(); + foreach ($metadata->lifecycleCallbacks as $name => $callbacks) { + foreach ($callbacks as $callback) { + if ($code = $this->_generateLifecycleCallbackMethod($name, $callback, $metadata)) { + $methods[] = $code; + } + } + } + return implode('', $methods); + } + } + + private function _generateEntityAssociationMappingProperties(ClassMetadataInfo $metadata) + { + $lines = array(); + foreach ($metadata->associationMappings as $associationMapping) { + if ($this->_hasProperty($associationMapping->sourceFieldName, $metadata)) { + continue; + } + if ($this->_generateAnnotations) { + $lines[] = $this->_generateAssociationMappingAnnotation($associationMapping, $metadata); + } + $lines[] = $this->_spaces . 'private $' . $associationMapping->sourceFieldName . ($associationMapping->isManyToMany() ? ' = array()' : null) . ";\n"; + } + $code = implode("\n", $lines); + return $code; + } + + private function _generateEntityFieldMappingProperties(ClassMetadataInfo $metadata) + { + $lines = array(); + foreach ($metadata->fieldMappings as $fieldMapping) { + if ($this->_hasProperty($fieldMapping['fieldName'], $metadata)) { + continue; + } + if ($this->_generateAnnotations) { + $lines[] = $this->_generateFieldMappingAnnotation($fieldMapping, $metadata); + } + $lines[] = $this->_spaces . 'private $' . $fieldMapping['fieldName'] . ";\n"; + } + $code = implode("\n", $lines); + return $code; + } + + private function _generateStubMethod($type, $fieldName, ClassMetadataInfo $metadata) + { + $methodName = $type . ucfirst($fieldName); + if ($this->_hasMethod($methodName, $metadata)) { + return; + } + + $method = array(); + $method[] = $this->_spaces . '/**'; + if ($type == 'get') { + $method[] = $this->_spaces . ' * Get ' . $fieldName; + } else if ($type == 'set') { + $method[] = $this->_spaces . ' * Set ' . $fieldName; + } else if ($type == 'add') { + $method[] = $this->_spaces . ' * Add ' . $fieldName; + } + $method[] = $this->_spaces . ' */'; + + if ($type == 'get') { + $method[] = $this->_spaces . 'public function ' . $methodName . '()'; + } else if ($type == 'set') { + $method[] = $this->_spaces . 'public function ' . $methodName . '($value)'; + } else if ($type == 'add') { + $method[] = $this->_spaces . 'public function ' . $methodName . '($value)'; + } + + $method[] = $this->_spaces . '{'; + if ($type == 'get') { + $method[] = $this->_spaces . $this->_spaces . 'return $this->' . $fieldName . ';'; + } else if ($type == 'set') { + $method[] = $this->_spaces . $this->_spaces . '$this->' . $fieldName . ' = $value;'; + } else if ($type == 'add') { + $method[] = $this->_spaces . $this->_spaces . '$this->' . $fieldName . '[] = $value;'; + } + + $method[] = $this->_spaces . '}'; + $method[] = "\n"; + + return implode("\n", $method); + } + + private function _generateLifecycleCallbackMethod($name, $methodName, $metadata) + { + if ($this->_hasMethod($methodName, $metadata)) { + return; + } + + $method = array(); + $method[] = $this->_spaces . '/**'; + $method[] = $this->_spaces . ' * @'.$name; + $method[] = $this->_spaces . ' */'; + $method[] = $this->_spaces . 'public function ' . $methodName . '()'; + $method[] = $this->_spaces . '{'; + $method[] = $this->_spaces . '}'; + + return implode("\n", $method)."\n\n"; + } + + private function _generateJoinColumnAnnotation(array $joinColumn) + { + $joinColumnAnnot = array(); + if (isset($joinColumn['name'])) { + $joinColumnAnnot[] = 'name="' . $joinColumn['name'] . '"'; + } + if (isset($joinColumn['referencedColumnName'])) { + $joinColumnAnnot[] = 'referencedColumnName="' . $joinColumn['referencedColumnName'] . '"'; + } + if (isset($joinColumn['unique']) && $joinColumn['unique']) { + $joinColumnAnnot[] = 'unique=' . ($joinColumn['unique'] ? 'true' : 'false'); + } + if (isset($joinColumn['nullable'])) { + $joinColumnAnnot[] = 'nullable=' . ($joinColumn['nullable'] ? 'true' : 'false'); + } + if (isset($joinColumn['onDelete'])) { + $joinColumnAnnot[] = 'onDelete=' . ($joinColumn['onDelete'] ? 'true' : 'false'); + } + if (isset($joinColumn['onUpdate'])) { + $joinColumnAnnot[] = 'onUpdate=' . ($joinColumn['onUpdate'] ? 'true' : 'false'); + } + if (isset($joinColumn['columnDefinition'])) { + $joinColumnAnnot[] = 'columnDefinition="' . $joinColumn['columnDefinition'] . '"'; + } + return '@JoinColumn(' . implode(', ', $joinColumnAnnot) . ')'; + } + + private function _generateAssociationMappingAnnotation(AssociationMapping $associationMapping, ClassMetadataInfo $metadata) + { + $e = explode('\\', get_class($associationMapping)); + $type = str_replace('Mapping', '', end($e)); + $typeOptions = array(); + if (isset($associationMapping->targetEntityName)) { + $typeOptions[] = 'targetEntity="' . $associationMapping->targetEntityName . '"'; + } + if (isset($associationMapping->mappedBy)) { + $typeOptions[] = 'mappedBy="' . $associationMapping->mappedBy . '"'; + } + if ($associationMapping->hasCascades()) { + $cascades = array(); + if ($associationMapping->isCascadePersist) $cascades[] = '"persist"'; + if ($associationMapping->isCascadeRemove) $cascades[] = '"remove"'; + if ($associationMapping->isCascadeDetach) $cascades[] = '"detach"'; + if ($associationMapping->isCascadeMerge) $cascades[] = '"merge"'; + if ($associationMapping->isCascadeRefresh) $cascades[] = '"refresh"'; + $typeOptions[] = 'cascade={' . implode(',', $cascades) . '}'; + } + if (isset($associationMapping->orphanRemoval) && $associationMapping->orphanRemoval) { + $typeOptions[] = 'orphanRemoval=' . ($associationMapping->orphanRemoval ? 'true' : 'false'); + } + + $lines = array(); + $lines[] = $this->_spaces . '/**'; + $lines[] = $this->_spaces . ' * @' . $type . '(' . implode(', ', $typeOptions) . ')'; + + if (isset($associationMapping->joinColumns) && $associationMapping->joinColumns) { + $lines[] = $this->_spaces . ' * @JoinColumns({'; + + $joinColumnsLines = array(); + foreach ($associationMapping->joinColumns as $joinColumn) { + if ($joinColumnAnnot = $this->_generateJoinColumnAnnotation($joinColumn)) { + $joinColumnsLines[] = $this->_spaces . ' * ' . $joinColumnAnnot; + } + } + $lines[] = implode(",\n", $joinColumnsLines); + $lines[] = $this->_spaces . ' * })'; + } + + if (isset($associationMapping->joinTable) && $associationMapping->joinTable) { + $joinTable = array(); + $joinTable[] = 'name="' . $associationMapping->joinTable['name'] . '"'; + if (isset($associationMapping->joinTable['schema'])) { + $joinTable[] = 'schema="' . $associationMapping->joinTable['schema'] . '"'; + } + + $lines[] = $this->_spaces . ' * @JoinTable(' . implode(', ', $joinTable) . ','; + + $lines[] = $this->_spaces . ' * joinColumns={'; + foreach ($associationMapping->joinTable['joinColumns'] as $joinColumn) { + $lines[] = $this->_spaces . ' * ' . $this->_generateJoinColumnAnnotation($joinColumn); + } + $lines[] = $this->_spaces . ' * },'; + + $lines[] = $this->_spaces . ' * inverseJoinColumns={'; + foreach ($associationMapping->joinTable['inverseJoinColumns'] as $joinColumn) { + $lines[] = $this->_spaces . ' * ' . $this->_generateJoinColumnAnnotation($joinColumn); + } + $lines[] = $this->_spaces . ' * }'; + + $lines[] = $this->_spaces . ' * )'; + } + + if (isset($associationMapping->orderBy)) { + $lines[] = $this->_spaces . ' * @OrderBy({'; + foreach ($associationMapping->orderBy as $name => $direction) { + $lines[] = $this->_spaces . ' * "' . $name . '"="' . $direction . '",'; + } + $lines[count($lines) - 1] = substr($lines[count($lines) - 1], 0, strlen($lines[count($lines) - 1]) - 1); + $lines[] = $this->_spaces . ' * })'; + } + + $lines[] = $this->_spaces . ' */'; + + return implode("\n", $lines); + } + + private function _generateFieldMappingAnnotation(array $fieldMapping, ClassMetadataInfo $metadata) + { + $lines = array(); + $lines[] = $this->_spaces . '/**'; + + $column = array(); + if (isset($fieldMapping['columnName'])) { + $column[] = 'name="' . $fieldMapping['columnName'] . '"'; + } + if (isset($fieldMapping['type'])) { + $column[] = 'type="' . $fieldMapping['type'] . '"'; + } + if (isset($fieldMapping['length'])) { + $column[] = 'length=' . $fieldMapping['length']; + } + if (isset($fieldMapping['precision'])) { + $column[] = 'precision=' . $fieldMapping['precision']; + } + if (isset($fieldMapping['scale'])) { + $column[] = 'scale=' . $fieldMapping['scale']; + } + if (isset($fieldMapping['nullable'])) { + $column[] = 'nullable=' . var_export($fieldMapping['nullable'], true); + } + if (isset($fieldMapping['columnDefinition'])) { + $column[] = 'columnDefinition="' . $fieldMapping['columnDefinition'] . '"'; + } + if (isset($fieldMapping['options'])) { + $options = array(); + foreach ($fieldMapping['options'] as $key => $value) { + $value = var_export($value, true); + $value = str_replace("'", '"', $value); + $options[] = ! is_numeric($key) ? $key . '=' . $value:$value; + } + if ($options) { + $column[] = 'options={' . implode(', ', $options) . '}'; + } + } + if (isset($fieldMapping['unique'])) { + $column[] = 'unique=' . var_export($fieldMapping['unique'], true); + } + $lines[] = $this->_spaces . ' * @Column(' . implode(', ', $column) . ')'; + if (isset($fieldMapping['id']) && $fieldMapping['id']) { + $lines[] = $this->_spaces . ' * @Id'; + if ($generatorType = $this->_getIdGeneratorTypeString($metadata->generatorType)) { + $lines[] = $this->_spaces.' * @GeneratedValue(strategy="' . $generatorType . '")'; + } + if ($metadata->sequenceGeneratorDefinition) { + $sequenceGenerator = array(); + if (isset($metadata->sequenceGeneratorDefinition['sequenceName'])) { + $sequenceGenerator[] = 'sequenceName="' . $metadata->sequenceGeneratorDefinition['sequenceName'] . '"'; + } + if (isset($metadata->sequenceGeneratorDefinition['allocationSize'])) { + $sequenceGenerator[] = 'allocationSize="' . $metadata->sequenceGeneratorDefinition['allocationSize'] . '"'; + } + if (isset($metadata->sequenceGeneratorDefinition['initialValue'])) { + $sequenceGenerator[] = 'initialValue="' . $metadata->sequenceGeneratorDefinition['initialValue'] . '"'; + } + $lines[] = $this->_spaces . ' * @SequenceGenerator(' . implode(', ', $sequenceGenerator) . ')'; + } + } + if (isset($fieldMapping['version']) && $fieldMapping['version']) { + $lines[] = $this->_spaces . ' * @Version'; + } + $lines[] = $this->_spaces . ' */'; + + return implode("\n", $lines); + } + + private function _getInheritanceTypeString($type) + { + switch ($type) + { + case ClassMetadataInfo::INHERITANCE_TYPE_NONE: + return 'NONE'; + break; + + case ClassMetadataInfo::INHERITANCE_TYPE_JOINED: + return 'JOINED'; + break; + + case ClassMetadataInfo::INHERITANCE_TYPE_SINGLE_TABLE: + return 'SINGLE_TABLE'; + break; + + case ClassMetadataInfo::INHERITANCE_TYPE_TABLE_PER_CLASS: + return 'PER_CLASS'; + break; + } + } + + private function _getChangeTrackingPolicyString($policy) + { + switch ($policy) + { + case ClassMetadataInfo::CHANGETRACKING_DEFERRED_IMPLICIT: + return 'DEFERRED_IMPLICIT'; + break; + + case ClassMetadataInfo::CHANGETRACKING_DEFERRED_EXPLICIT: + return 'DEFERRED_EXPLICIT'; + break; + + case ClassMetadataInfo::CHANGETRACKING_NOTIFY: + return 'NOTIFY'; + break; + } + } + + private function _getIdGeneratorTypeString($type) + { + switch ($type) + { + case ClassMetadataInfo::GENERATOR_TYPE_AUTO: + return 'AUTO'; + break; + + case ClassMetadataInfo::GENERATOR_TYPE_SEQUENCE: + return 'SEQUENCE'; + break; + + case ClassMetadataInfo::GENERATOR_TYPE_TABLE: + return 'TABLE'; + break; + + case ClassMetadataInfo::GENERATOR_TYPE_IDENTITY: + return 'IDENTITY'; + break; + } + } +} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Tools/Export/Driver/AnnotationExporter.php b/lib/Doctrine/ORM/Tools/Export/Driver/AnnotationExporter.php index 045e3fd97..648ccde88 100644 --- a/lib/Doctrine/ORM/Tools/Export/Driver/AnnotationExporter.php +++ b/lib/Doctrine/ORM/Tools/Export/Driver/AnnotationExporter.php @@ -23,7 +23,8 @@ namespace Doctrine\ORM\Tools\Export\Driver; use Doctrine\ORM\Mapping\ClassMetadataInfo, - Doctrine\ORM\Mapping\AssociationMapping; + Doctrine\ORM\Mapping\AssociationMapping, + Doctrine\ORM\Tools\EntityGenerator; /** * ClassMetadata exporter for PHP classes with annotations @@ -37,24 +38,12 @@ use Doctrine\ORM\Mapping\ClassMetadataInfo, class AnnotationExporter extends AbstractExporter { protected $_extension = '.php'; + private $_generator; - private $_isNew = false; - private $_outputPath; - private $_numSpaces; - private $_spaces; - private $_classToExtend; - private $_currentCode; - - /** - * Constructor - * - * @param string $dir Diretory to fetch for metadatas - */ public function __construct($dir = null) { parent::__construct($dir); - - $this->setNumSpaces(4); + $this->_generator = new EntityGenerator(); } /** @@ -66,53 +55,11 @@ class AnnotationExporter extends AbstractExporter */ public function exportClassMetadata(ClassMetadataInfo $metadata) { - $this->_currentCode = null; - - if (file_exists($this->_outputPath)) { - $this->_currentCode = file_get_contents($this->_outputPath); - } - - ob_start(); - include($this->_isNew ? 'annotation.tpl.php' : 'annotation_body.tpl.php'); - $code = ob_get_contents(); - ob_end_clean(); - - $code = str_replace(array('[?php', '?]'), array(''), $code); - $code = explode("\n", $code); - - if ($this->_currentCode) { - $body = $code; - $code = $this->_currentCode; - $code = explode("\n", $code); - - unset($code[array_search('}', $code)]); - - foreach ($body as $line) { - $code[] = $line; - } - - $code[] = '}'; - } - - $code = array_values($code); - - // Remove empty lines before last "}" - for ($i = count($code) - 1; $i > 0; --$i) { - $line = trim($code[$i]); - - if ($line && $line != '}') { - break; - } - - if ( ! $line) { - unset($code[$i]); - } - } - - $code = array_values($code); - $exported = implode("\n", $code); - - return $exported; + $this->_generator->setGenerateAnnotations(true); + $this->_generator->setGenerateStubMethods(false); + $this->_generator->setRegenerateEntityIfExists(false); + $this->_generator->setUpdateEntityIfExists(false); + $this->_generator->writeEntityClass($metadata, $this->_outputDir); } /** @@ -123,8 +70,7 @@ class AnnotationExporter extends AbstractExporter */ public function setNumSpaces($numSpaces) { - $this->_spaces = str_repeat(' ', $numSpaces); - $this->_numSpaces = $numSpaces; + $this->_generator->setNumSpaces($numSpaces); } /** @@ -134,475 +80,6 @@ class AnnotationExporter extends AbstractExporter */ public function setClassToExtend($classToExtend) { - $this->_classToExtend = $classToExtend; - } - - /** - * This method is overriden so that each class is outputted - * to the appropriate path where namespaces become directories. - * - * Export each ClassMetadata instance to a single Doctrine Mapping file - * named after the entity - * - * @return void - */ - public function export() - { - if ( ! is_dir($this->_outputDir)) { - mkdir($this->_outputDir, 0777); - } - - foreach ($this->_metadatas as $metadata) { - $outputPath = $this->_outputDir . '/' . str_replace('\\', DIRECTORY_SEPARATOR, $metadata->name) . $this->_extension; - $outputDir = dirname($outputPath); - - if ( ! is_dir($outputDir)) { - mkdir($outputDir, 0777, true); - } - - if ( ! file_exists($outputPath)) { - $this->_isNew = true; - } - - $this->_outputPath = $outputPath; - $output = $this->exportClassMetadata($metadata); - - file_put_contents($outputPath, $output); - } - } - - private function _hasProperty($property, $metadata) - { - if ($this->_isNew) { - return false; - } else { - return strpos($this->_currentCode, '$' . $property) !== false ? true : false; - } - } - - private function _hasMethod($method, $metadata) - { - if ($this->_isNew) { - return false; - } else { - return strpos($this->_currentCode, 'function ' . $method) !== false ? true : false; - } - } - - private function _hasNamespace($metadata) - { - return strpos($metadata->name, '\\') ? true : false; - } - - private function _extendsClass() - { - return $this->_classToExtend ? true : false; - } - - private function _getClassToExtend() - { - return $this->_classToExtend; - } - - private function _getClassToExtendName() - { - $refl = new \ReflectionClass($this->_getClassToExtend()); - return $refl->getShortName(); - } - - private function _getClassToExtendNamespace() - { - $refl = new \ReflectionClass($this->_getClassToExtend()); - return $refl->getNamespaceName() ? $refl->getNamespaceName():$refl->getShortName(); - } - - private function _getClassName($metadata) - { - if ($pos = strrpos($metadata->name, '\\')) { - return substr($metadata->name, $pos + 1, strlen($metadata->name)); - } else { - return $metadata->name; - } - } - - private function _getNamespace($metadata) - { - return substr($metadata->name, 0, strrpos($metadata->name, '\\')); - } - - private function _getEntityAnnotation($metadata) - { - $lines = array(); - $lines[] = '/**'; - - $methods = array( - '_getTableAnnotation', - '_getInheritanceAnnotation', - '_getDiscriminatorColumnAnnotation', - '_getDiscriminatorMapAnnotation' - ); - - foreach ($methods as $method) { - if ($code = $this->$method($metadata)) { - $lines[] = ' * ' . $code; - } - } - - if ($metadata->isMappedSuperclass) { - $lines[] = ' * @MappedSupperClass'; - } else { - $lines[] = ' * @Entity'; - } - - if ($metadata->customRepositoryClassName) { - $lines[count($lines) - 1] .= '(repositoryClass="' . $metadata->customRepositoryClassName . '")'; - } - - if (isset($metadata->lifecycleCallbacks) && $metadata->lifecycleCallbacks) { - $lines[] = ' * @HasLifecycleCallbacks'; - } - - $lines[] = ' */'; - $lines[] = ''; - - return implode("\n", $lines); - } - - private function _getTableAnnotation($metadata) - { - $table = array(); - $table[] = 'name="' . $metadata->primaryTable['name'] . '"'; - - if (isset($metadata->primaryTable['schema'])) { - $table[] = 'schema="' . $metadata->primaryTable['schema'] . '"'; - } - - return '@Table(' . implode(', ', $table) . ')'; - } - - private function _getInheritanceAnnotation($metadata) - { - if ($metadata->inheritanceType != ClassMetadataInfo::INHERITANCE_TYPE_NONE) { - switch ($metadata->inheritanceType) { - case ClassMetadataInfo::INHERITANCE_TYPE_JOINED: - $type = "JOINED"; - break; - - case ClassMetadataInfo::INHERITANCE_TYPE_SINGLE_TABLE: - $type = "SINGLE_TABLE"; - break; - - case ClassMetadataInfo::INHERITANCE_TYPE_TABLE_PER_CLASS: - $type = "TABLE_PER_CLASS"; - break; - } - - return '@InheritanceType("'.$type.'")'; - } - - return ''; - } - - private function _getDiscriminatorColumnAnnotation($metadata) - { - if ($metadata->inheritanceType != ClassMetadataInfo::INHERITANCE_TYPE_NONE) { - $discrColumn = $metadata->discriminatorValue; - $columnDefinition = 'name="' . $discrColumn['name'] - . '", type="' . $discrColumn['type'] - . '", length=' . $discrColumn['length']; - - return '@DiscriminatorColumn(' . $columnDefinition . ')'; - } - - return ''; - } - - private function _getDiscriminatorMapAnnotation($metadata) - { - if ($metadata->inheritanceType != ClassMetadataInfo::INHERITANCE_TYPE_NONE) { - $inheritanceClassMap = array(); - - foreach ($metadata->discriminatorMap as $type => $class) { - $inheritanceClassMap[] .= '"' . $type . '" = "' . $class . '"'; - } - - return '@DiscriminatorMap({' . implode(', ', $inheritanceClassMap) . '})'; - } - - return ''; - } - - private function _addMethod($type, $fieldName, $metadata, array &$methods) - { - $methodName = $type . ucfirst($fieldName); - if ($this->_hasMethod($methodName, $metadata)) { - return false; - } - - $method = array(); - $method[] = $this->_spaces . '/**'; - if ($type == 'get') { - $method[] = $this->_spaces . ' * Get ' . $fieldName; - } else if ($type == 'set') { - $method[] = $this->_spaces . ' * Set ' . $fieldName; - } else if ($type == 'add') { - $method[] = $this->_spaces . ' * Add ' . $fieldName; - } - $method[] = $this->_spaces . ' */'; - - if ($type == 'get') { - $method[] = $this->_spaces . 'public function ' . $methodName . '()'; - } else if ($type == 'set') { - $method[] = $this->_spaces . 'public function ' . $methodName . '($value)'; - } else if ($type == 'add') { - $method[] = $this->_spaces . 'public function ' . $methodName . '($value)'; - } - - $method[] = $this->_spaces . '{'; - if ($type == 'get') { - $method[] = $this->_spaces . $this->_spaces . 'return $this->' . $fieldName . ';'; - } else if ($type == 'set') { - $method[] = $this->_spaces . $this->_spaces . '$this->' . $fieldName . ' = $value;'; - } else if ($type == 'add') { - $method[] = $this->_spaces . $this->_spaces . '$this->' . $fieldName . '[] = $value;'; - } - - $method[] = $this->_spaces . '}'; - $method[] = "\n"; - - $methods[] = implode("\n", $method); - } - - private function _addLifecycleCallbackMethod($name, $methodName, $metadata, array &$methods) - { - if ($this->_hasMethod($methodName, $metadata)) { - return false; - } - - $method = array(); - $method[] = $this->_spaces . '/**'; - $method[] = $this->_spaces . ' * @'.$name; - $method[] = $this->_spaces . ' */'; - $method[] = $this->_spaces . 'public function ' . $methodName . '()'; - $method[] = $this->_spaces . '{'; - $method[] = $this->_spaces . '}'; - - $methods[] = implode("\n", $method)."\n\n"; - } - - private function _getMethods($metadata) - { - $methods = array(); - - foreach ($metadata->fieldMappings as $fieldMapping) { - if ( ! isset($fieldMapping['id']) || ! $fieldMapping['id']) { - $this->_addMethod('set', $fieldMapping['fieldName'], $metadata, $methods); - } - - $this->_addMethod('get', $fieldMapping['fieldName'], $metadata, $methods); - } - - foreach ($metadata->associationMappings as $associationMapping) { - if ($associationMapping instanceof \Doctrine\ORM\Mapping\OneToOneMapping) { - $this->_addMethod('set', $associationMapping->sourceFieldName, $metadata, $methods); - $this->_addMethod('get', $associationMapping->sourceFieldName, $metadata, $methods); - } else if ($associationMapping instanceof \Doctrine\ORM\Mapping\OneToManyMapping) { - if ($associationMapping->isOwningSide) { - $this->_addMethod('set', $associationMapping->sourceFieldName, $metadata, $methods); - $this->_addMethod('get', $associationMapping->sourceFieldName, $metadata, $methods); - } else { - $this->_addMethod('add', $associationMapping->sourceFieldName, $metadata, $methods); - $this->_addMethod('get', $associationMapping->sourceFieldName, $metadata, $methods); - } - } else if ($associationMapping instanceof \Doctrine\ORM\Mapping\ManyToManyMapping) { - $this->_addMethod('add', $associationMapping->sourceFieldName, $metadata, $methods); - $this->_addMethod('get', $associationMapping->sourceFieldName, $metadata, $methods); - } - } - - if (isset($metadata->lifecycleCallbacks) && $metadata->lifecycleCallbacks) { - foreach ($metadata->lifecycleCallbacks as $name => $callbacks) { - foreach ($callbacks as $callback) { - $this->_addLifecycleCallbackMethod($name, $callback, $metadata, $methods); - } - } - } - - return $methods; - } - - private function _getJoinColumnAnnotation(array $joinColumn) - { - $joinColumnAnnot = array(); - if (isset($joinColumn['name'])) { - $joinColumnAnnot[] = 'name="' . $joinColumn['name'] . '"'; - } - if (isset($joinColumn['referencedColumnName'])) { - $joinColumnAnnot[] = 'referencedColumnName="' . $joinColumn['referencedColumnName'] . '"'; - } - if (isset($joinColumn['unique']) && $joinColumn['unique']) { - $joinColumnAnnot[] = 'unique=' . ($joinColumn['unique'] ? 'true' : 'false'); - } - if (isset($joinColumn['nullable'])) { - $joinColumnAnnot[] = 'nullable=' . ($joinColumn['nullable'] ? 'true' : 'false'); - } - if (isset($joinColumn['onDelete'])) { - $joinColumnAnnot[] = 'onDelete=' . ($joinColumn['onDelete'] ? 'true' : 'false'); - } - if (isset($joinColumn['onUpdate'])) { - $joinColumnAnnot[] = 'onUpdate=' . ($joinColumn['onUpdate'] ? 'true' : 'false'); - } - if (isset($joinColumn['columnDefinition'])) { - $joinColumnAnnot[] = 'columnDefinition="' . $joinColumn['columnDefinition'] . '"'; - } - return '@JoinColumn(' . implode(', ', $joinColumnAnnot) . ')'; - } - - private function _getAssociationMappingAnnotation(AssociationMapping $associationMapping, ClassMetadataInfo $metadata) - { - $e = explode('\\', get_class($associationMapping)); - $type = str_replace('Mapping', '', end($e)); - $typeOptions = array(); - if (isset($associationMapping->targetEntityName)) { - $typeOptions[] = 'targetEntity="' . $associationMapping->targetEntityName . '"'; - } - if (isset($associationMapping->mappedBy)) { - $typeOptions[] = 'mappedBy="' . $associationMapping->mappedBy . '"'; - } - if ($associationMapping->hasCascades()) { - $cascades = array(); - if ($associationMapping->isCascadePersist) $cascades[] = '"persist"'; - if ($associationMapping->isCascadeRemove) $cascades[] = '"remove"'; - if ($associationMapping->isCascadeDetach) $cascades[] = '"detach"'; - if ($associationMapping->isCascadeMerge) $cascades[] = '"merge"'; - if ($associationMapping->isCascadeRefresh) $cascades[] = '"refresh"'; - $typeOptions[] = 'cascade={' . implode(',', $cascades) . '}'; - } - if (isset($associationMapping->orphanRemoval) && $associationMapping->orphanRemoval) { - $typeOptions[] = 'orphanRemoval=' . ($associationMapping->orphanRemoval ? 'true' : 'false'); - } - - $lines = array(); - $lines[] = $this->_spaces . '/**'; - $lines[] = $this->_spaces . ' * @' . $type . '(' . implode(', ', $typeOptions) . ')'; - - if (isset($associationMapping->joinColumns) && $associationMapping->joinColumns) { - $lines[] = $this->_spaces . ' * @JoinColumns({'; - - $joinColumnsLines = array(); - foreach ($associationMapping->joinColumns as $joinColumn) { - if ($joinColumnAnnot = $this->_getJoinColumnAnnotation($joinColumn)) { - $joinColumnsLines[] = $this->_spaces . ' * ' . $joinColumnAnnot; - } - } - $lines[] = implode(",\n", $joinColumnsLines); - $lines[] = $this->_spaces . ' * })'; - } - - if (isset($associationMapping->joinTable) && $associationMapping->joinTable) { - $joinTable = array(); - $joinTable[] = 'name="' . $associationMapping->joinTable['name'] . '"'; - if (isset($associationMapping->joinTable['schema'])) { - $joinTable[] = 'schema="' . $associationMapping->joinTable['schema'] . '"'; - } - - $lines[] = $this->_spaces . ' * @JoinTable(' . implode(', ', $joinTable) . ','; - - $lines[] = $this->_spaces . ' * joinColumns={'; - foreach ($associationMapping->joinTable['joinColumns'] as $joinColumn) { - $lines[] = $this->_spaces . ' * ' . $this->_getJoinColumnAnnotation($joinColumn); - } - $lines[] = $this->_spaces . ' * },'; - - $lines[] = $this->_spaces . ' * inverseJoinColumns={'; - foreach ($associationMapping->joinTable['inverseJoinColumns'] as $joinColumn) { - $lines[] = $this->_spaces . ' * ' . $this->_getJoinColumnAnnotation($joinColumn); - } - $lines[] = $this->_spaces . ' * }'; - - $lines[] = $this->_spaces . ' * )'; - } - - if (isset($associationMapping->orderBy)) { - $lines[] = $this->_spaces . ' * @OrderBy({'; - foreach ($associationMapping->orderBy as $name => $direction) { - $lines[] = $this->_spaces . ' * "' . $name . '"="' . $direction . '",'; - } - $lines[count($lines) - 1] = substr($lines[count($lines) - 1], 0, strlen($lines[count($lines) - 1]) - 1); - $lines[] = $this->_spaces . ' * })'; - } - - $lines[] = $this->_spaces . ' */'; - - return implode("\n", $lines); - } - - private function _getFieldMappingAnnotation(array $fieldMapping, ClassMetadataInfo $metadata) - { - $lines = array(); - $lines[] = $this->_spaces . '/**'; - - $column = array(); - if (isset($fieldMapping['columnName'])) { - $column[] = 'name="' . $fieldMapping['columnName'] . '"'; - } - if (isset($fieldMapping['type'])) { - $column[] = 'type="' . $fieldMapping['type'] . '"'; - } - if (isset($fieldMapping['length'])) { - $column[] = 'length=' . $fieldMapping['length']; - } - if (isset($fieldMapping['precision'])) { - $column[] = 'precision=' . $fieldMapping['precision']; - } - if (isset($fieldMapping['scale'])) { - $column[] = 'scale=' . $fieldMapping['scale']; - } - if (isset($fieldMapping['nullable'])) { - $column[] = 'nullable=' . var_export($fieldMapping['nullable'], true); - } - if (isset($fieldMapping['columnDefinition'])) { - $column[] = 'columnDefinition="' . $fieldMapping['columnDefinition'] . '"'; - } - if (isset($fieldMapping['options'])) { - $options = array(); - foreach ($fieldMapping['options'] as $key => $value) { - $value = var_export($value, true); - $value = str_replace("'", '"', $value); - $options[] = ! is_numeric($key) ? $key . '=' . $value:$value; - } - if ($options) { - $column[] = 'options={' . implode(', ', $options) . '}'; - } - } - if (isset($fieldMapping['unique'])) { - $column[] = 'unique=' . var_export($fieldMapping['unique'], true); - } - $lines[] = $this->_spaces . ' * @Column(' . implode(', ', $column) . ')'; - if (isset($fieldMapping['id']) && $fieldMapping['id']) { - $lines[] = $this->_spaces . ' * @Id'; - if ($generatorType = $this->_getIdGeneratorTypeString($metadata->generatorType)) { - $lines[] = $this->_spaces.' * @GeneratedValue(strategy="' . $generatorType . '")'; - } - if ($metadata->sequenceGeneratorDefinition) { - $sequenceGenerator = array(); - if (isset($metadata->sequenceGeneratorDefinition['sequenceName'])) { - $sequenceGenerator[] = 'sequenceName="' . $metadata->sequenceGeneratorDefinition['sequenceName'] . '"'; - } - if (isset($metadata->sequenceGeneratorDefinition['allocationSize'])) { - $sequenceGenerator[] = 'allocationSize="' . $metadata->sequenceGeneratorDefinition['allocationSize'] . '"'; - } - if (isset($metadata->sequenceGeneratorDefinition['initialValue'])) { - $sequenceGenerator[] = 'initialValue="' . $metadata->sequenceGeneratorDefinition['initialValue'] . '"'; - } - $lines[] = $this->_spaces . ' * @SequenceGenerator(' . implode(', ', $sequenceGenerator) . ')'; - } - } - if (isset($fieldMapping['version']) && $fieldMapping['version']) { - $lines[] = $this->_spaces . ' * @Version'; - } - $lines[] = $this->_spaces . ' */'; - - return implode("\n", $lines); + $this->_generator->setClassToExtend($classToExtend); } } \ No newline at end of file diff --git a/tests/Doctrine/Tests/ORM/Tools/AllTests.php b/tests/Doctrine/Tests/ORM/Tools/AllTests.php index 30d50a7be..a729044df 100644 --- a/tests/Doctrine/Tests/ORM/Tools/AllTests.php +++ b/tests/Doctrine/Tests/ORM/Tools/AllTests.php @@ -26,6 +26,7 @@ class AllTests $suite->addTestSuite('Doctrine\Tests\ORM\Tools\Export\AnnotationClassMetadataExporterTest'); $suite->addTestSuite('Doctrine\Tests\ORM\Tools\ConvertDoctrine1SchemaTest'); $suite->addTestSuite('Doctrine\Tests\ORM\Tools\SchemaToolTest'); + $suite->addTestSuite('Doctrine\Tests\ORM\Tools\EntityGeneratorTest'); return $suite; } diff --git a/tests/Doctrine/Tests/ORM/Tools/EntityGeneratorTest.php b/tests/Doctrine/Tests/ORM/Tools/EntityGeneratorTest.php new file mode 100644 index 000000000..c6cda38fc --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Tools/EntityGeneratorTest.php @@ -0,0 +1,79 @@ +primaryTable['name'] = 'book'; + $metadata->mapField(array('fieldName' => 'name', 'type' => 'varchar')); + $metadata->mapField(array('fieldName' => 'id', 'type' => 'integer', 'id' => true)); + $metadata->mapOneToOne(array('fieldName' => 'other', 'targetEntity' => 'Other', 'mappedBy' => 'this')); + $joinColumns = array( + array('name' => 'other_id', 'referencedColumnName' => 'id') + ); + $metadata->mapOneToOne(array('fieldName' => 'association', 'targetEntity' => 'Other', 'joinColumns' => $joinColumns)); + $metadata->mapManyToMany(array( + 'fieldName' => 'author', + 'targetEntity' => 'Author', + 'joinTable' => array( + 'name' => 'book_author', + 'joinColumns' => array(array('name' => 'bar_id', 'referencedColumnName' => 'id')), + 'inverseJoinColumns' => array(array('name' => 'baz_id', 'referencedColumnName' => 'id')), + ), + )); + $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO); + + $generator = new EntityGenerator(); + $generator->setGenerateAnnotations(true); + $generator->setGenerateStubMethods(true); + $generator->setRegenerateEntityIfExists(false); + $generator->setUpdateEntityIfExists(true); + $generator->writeEntityClass($metadata, __DIR__); + + $path = __DIR__ . '/EntityGeneratorBook.php'; + $this->assertTrue(file_exists($path)); + require_once $path; + } + + /** + * @depends testWriteEntityClass + */ + public function testGeneratedEntityClassMethods() + { + $this->assertTrue(method_exists('\EntityGeneratorBook', 'getId')); + $this->assertTrue(method_exists('\EntityGeneratorBook', 'setName')); + $this->assertTrue(method_exists('\EntityGeneratorBook', 'getName')); + $this->assertTrue(method_exists('\EntityGeneratorBook', 'setOther')); + $this->assertTrue(method_exists('\EntityGeneratorBook', 'getOther')); + $this->assertTrue(method_exists('\EntityGeneratorBook', 'setAssociation')); + $this->assertTrue(method_exists('\EntityGeneratorBook', 'getAssociation')); + $this->assertTrue(method_exists('\EntityGeneratorBook', 'getAuthor')); + $this->assertTrue(method_exists('\EntityGeneratorBook', 'addAuthor')); + + $book = new \EntityGeneratorBook(); + + $book->setName('Jonathan H. Wage'); + $this->assertEquals('Jonathan H. Wage', $book->getName()); + + $book->setOther('Other'); + $this->assertEquals('Other', $book->getOther()); + + $book->setAssociation('Test'); + $this->assertEquals('Test', $book->getAssociation()); + + $book->addAuthor('Test'); + $this->assertEquals(array('Test'), $book->getAuthor()); + + unlink(__DIR__ . '/EntityGeneratorBook.php'); + } +} \ No newline at end of file