Commit 089b5dd8 authored by jwage's avatar jwage

[2.0] Refactoring code for reading multiple sources of mapping information...

[2.0] Refactoring code for reading multiple sources of mapping information from ClassMetadataExporter to a new ClassMetadataReader tool so it can be used to read mapping information easily from multiple different sources. This is used for generating repositories, converting mapping information, generating entity stubs, etc. Generally though, it is useful to be able to read the information for some mapping files into an array of ClassMetadataInfo instances without it being bound to the ORM and the metadata referenced by the EntityManager ClassMetadataFactory
parent 49076b7b
......@@ -84,7 +84,8 @@ class CliController extends AbstractNamespace
->addTask('schema-tool', $ns . '\SchemaToolTask')
->addTask('version', $ns . '\VersionTask')
->addTask('convert-d1-schema', $ns . '\ConvertDoctrine1SchemaTask')
->addTask('generate-entities', $ns . '\GenerateEntitiesTask');
->addTask('generate-entities', $ns . '\GenerateEntitiesTask')
->addTask('generate-repositories', $ns . '\GenerateRepositoriesTask');
$ns = 'Doctrine\DBAL\Tools\Cli\Tasks';
$this->addNamespace('Dbal')
......
......@@ -243,13 +243,14 @@ class ProxyFactory
/** Reference Proxy class code template */
private static $_proxyClassTemplate =
'<?php
namespace <namespace>
{
/**
namespace <namespace>;
/**
* THIS CLASS WAS GENERATED BY THE DOCTRINE ORM. DO NOT EDIT THIS FILE.
*/
class <proxyClassName> extends \<className> implements \Doctrine\ORM\Proxy\Proxy
{
class <proxyClassName> extends \<className> implements \Doctrine\ORM\Proxy\Proxy
{
private $_entityPersister;
private $_identifier;
public $__isInitialized__ = false;
......@@ -279,6 +280,5 @@ namespace <namespace>
}
<sleepImpl>
}
}
}';
}
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Tools;
use Doctrine\ORM\Mapping\ClassMetadataInfo,
Doctrine\ORM\Mapping\ClassMetadata,
Doctrine\ORM\Mapping\MappingException,
Doctrine\ORM\Mapping\Driver\Driver,
Doctrine\ORM\Mapping\Driver\AnnotationDriver,
Doctrine\ORM\EntityManager;
/**
* Class to read metadata mapping information from multiple sources into an array
* of ClassMetadataInfo instances.
*
* The difference between this class and the ClassMetadataFactory is that this
* is just a tool for reading in the mapping information from files without
* having it bound to the actual ORM and the mapping information referenced by
* the EntityManager. This allows us to read any source of mapping information
* and return a single array of aggregated ClassMetadataInfo instances.
*
* These arrays are used for exporting the mapping information to the supported
* mapping drivers, generating entities, generating repositories, etc.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class ClassMetadataReader
{
private static $_mappingDrivers = array(
'annotation' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
'yaml' => 'Doctrine\ORM\Mapping\Driver\YamlDriver',
'yml' => 'Doctrine\ORM\Mapping\Driver\YamlDriver',
'xml' => 'Doctrine\ORM\Mapping\Driver\XmlDriver',
'php' => 'Doctrine\ORM\Mapping\Driver\PhpDriver',
'database' => 'Doctrine\ORM\Mapping\Driver\DatabaseDriver'
);
private $_mappingSources = array();
private $_em;
/**
* Register a new mapping driver class under a specified name
*
* @param string $name
* @param string $class
*/
public static function registerMappingDriver($name, $class)
{
self::$_mappingDrivers[$name] = $class;
}
/**
* Optionally set the EntityManager instance to get the AnnotationDriver
* from instead of creating a new instance of the AnnotationDriver
*
* @param EntityManager $em
* @return void
*/
public function setEntityManager(EntityManager $em)
{
$this->_em = $em;
}
/**
* Get an array of ClassMetadataInfo instances for all the configured mapping
* directories. Reads the mapping directories and populates ClassMetadataInfo
* instances.
*
* @return array $classes
*/
public function getMetadatas()
{
$classes = array();
foreach ($this->_mappingSources as $d) {
list($source, $driver) = $d;
$allClasses = $driver->getAllClassNames();
foreach ($allClasses as $className) {
if (class_exists($className, false)) {
$metadata = new ClassMetadata($className);
} else {
$metadata = new ClassMetadataInfo($className);
}
$driver->loadMetadataForClass($className, $metadata);
if ( ! $metadata->isMappedSuperclass) {
$classes[$metadata->name] = $metadata;
}
}
}
return $classes;
}
/**
* Add a new mapping directory to the array of directories to convert and export
* to another format
*
* @param string $source The source for the mapping
* @param string $type The type of mapping files (yml, xml, etc.)
* @return void
*/
public function addMappingSource($source, $type = null)
{
if ($type === null) {
$type = $this->_determineSourceType($source);
}
if ( ! isset(self::$_mappingDrivers[$type])) {
throw ExportException::invalidMappingDriverType($type);
}
$source = $this->_getSourceByType($type, $source);
$driver = $this->_getMappingDriver($type, $source);
$this->_mappingSources[] = array($source, $driver);
}
/**
* Get an instance of a mapping driver
*
* @param string $type The type of mapping driver (yaml, xml, annotation, etc.)
* @param string $source The source for the driver
* @return AbstractDriver $driver
*/
private function _getMappingDriver($type, $source = null)
{
if ($source instanceof \Doctrine\ORM\Mapping\Driver\Driver) {
return $source;
}
if ( ! isset(self::$_mappingDrivers[$type])) {
return false;
}
$class = self::$_mappingDrivers[$type];
if (is_subclass_of($class, 'Doctrine\ORM\Mapping\Driver\AbstractFileDriver')) {
if (is_null($source)) {
throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath();
}
$driver = new $class($source);
} else if ($class == 'Doctrine\ORM\Mapping\Driver\AnnotationDriver') {
$reader = new \Doctrine\Common\Annotations\AnnotationReader(new \Doctrine\Common\Cache\ArrayCache);
$reader->setDefaultAnnotationNamespace('Doctrine\ORM\Mapping\\');
$driver = new \Doctrine\ORM\Mapping\Driver\AnnotationDriver($reader, $source);
} else {
$driver = new $class($source);
}
return $driver;
}
private function _determineSourceType($source)
{
// If the --from=<VALUE> is a directory lets determine if it is
// annotations, yaml, xml, etc.
if (is_dir($source)) {
$source = realpath($source);
// Find the files in the directory
$files = glob($source . '/*.*');
if ( ! $files) {
throw new \InvalidArgumentException(
sprintf('No mapping files found in "%s"', $source)
);
}
// Get the contents of the first file
$contents = file_get_contents($files[0]);
// Check if it has a class definition in it for annotations
if (preg_match("/class (.*)/", $contents)) {
return 'annotation';
// Otherwise lets determine the type based on the extension of the
// first file in the directory (yml, xml, etc)
} else {
$info = pathinfo($files[0]);
return $info['extension'];
}
// Nothing special for database
} else if ($source == 'database') {
return 'database';
}
}
private function _getSourceByType($type, $source)
{
$source = realpath($source);
// If --from==database then the source is an instance of SchemaManager
// for the current EntityMAnager
if ($type == 'database' && $this->_em) {
return $this->_em->getConnection()->getSchemaManager();
// If source is annotation then lets try and find the existing annotation
// driver for the source instead of re-creating a new instance
} else if ($type == 'annotation') {
if ($this->_em) {
$metadataDriverImpl = $this->_em->getConfiguration()->getMetadataDriverImpl();
// Find the annotation driver in the chain of drivers
if ($metadataDriverImpl instanceof DriverChain) {
foreach ($metadataDriverImpl->getDrivers() as $namespace => $driver) {
if ($this->_isAnnotationDriverForPath($driver, $source)) {
return $driver;
}
}
} else if ($this->_isAnnotationDriverForPath($metadataDriverImpl, $source)) {
return $metadataDriverImpl;
} else if ($metadataDriverImpl instanceof AnnotationDriver) {
$metadataDriverImpl->addPaths(array($source));
return $metadataDriverImpl;
} else {
return $source;
}
} else {
return $source;
}
} else {
return $source;
}
}
/**
* Check to see if the given metadata driver is the annotation driver for the
* given directory path
*
* @param Driver $driver
* @param string $path
* @return boolean
*/
private function _isAnnotationDriverForPath(Driver $driver, $path)
{
if ( ! $driver instanceof AnnotationDriver) {
return false;
}
if (in_array(realpath($path), $driver->getPaths())) {
return true;
} else {
return false;
}
}
}
\ No newline at end of file
......@@ -91,7 +91,7 @@ class ConvertDoctrine1SchemaTask extends AbstractTask
$exporter = $cme->getExporter($arguments['to'], $arguments['dest']);
$converter = new ConvertDoctrine1Schema($arguments['from']);
$metadatas = $converter->getMetadatasFromSchema();
$metadatas = $converter->getMetadatas();
foreach ($metadatas as $metadata) {
$printer->writeln(
......
......@@ -114,6 +114,7 @@ class ConvertMappingTask extends AbstractTask
{
$arguments = $this->getArguments();
$cme = new ClassMetadataExporter();
$cme->setEntityManager($this->getConfiguration()->getAttribute('em'));
$printer = $this->getPrinter();
// Get exporter and configure it
......@@ -130,28 +131,10 @@ class ConvertMappingTask extends AbstractTask
$from = (array) $arguments['from'];
foreach ($from as $source) {
$sourceArg = $source;
$type = $this->_determineSourceType($sourceArg);
if ( ! $type) {
throw new CliException(
"Invalid mapping source type '$sourceArg'."
);
}
$source = $this->_getSourceByType($type, $sourceArg);
$printer->writeln(
sprintf(
'Adding "%s" mapping source which contains the "%s" format',
$printer->format($sourceArg, 'KEYWORD'), $printer->format($type, 'KEYWORD')
)
);
$cme->addMappingSource($source, $type);
$cme->addMappingSource($source);
}
$metadatas = $cme->getMetadatasForMappingSources();
$metadatas = $cme->getMetadatas();
foreach ($metadatas as $metadata) {
$printer->writeln(
......@@ -159,9 +142,10 @@ class ConvertMappingTask extends AbstractTask
);
}
$printer->writeln('');
$printer->writeln(
sprintf(
'Exporting "%s" mapping information to directory "%s"',
'Exporting "%s" mapping information to "%s"',
$printer->format($arguments['to'], 'KEYWORD'),
$printer->format($arguments['dest'], 'KEYWORD')
)
......@@ -170,88 +154,4 @@ class ConvertMappingTask extends AbstractTask
$exporter->setMetadatas($metadatas);
$exporter->export();
}
protected function _determineSourceType($source)
{
// If the --from=<VALUE> is a directory lets determine if it is
// annotations, yaml, xml, etc.
if (is_dir($source)) {
// Find the files in the directory
$files = glob($source . '/*.*');
if ( ! $files) {
throw new \InvalidArgumentException(
sprintf('No mapping files found in "%s"', $source)
);
}
// Get the contents of the first file
$contents = file_get_contents($files[0]);
// Check if it has a class definition in it for annotations
if (preg_match("/class (.*)/", $contents)) {
return 'annotation';
// Otherwise lets determine the type based on the extension of the
// first file in the directory (yml, xml, etc)
} else {
$info = pathinfo($files[0]);
return $info['extension'];
}
// Nothing special for database
} else if ($source == 'database') {
return 'database';
}
}
protected function _getSourceByType($type, $source)
{
// If --from==database then the source is an instance of SchemaManager
// for the current EntityMAnager
if ($type == 'database') {
$em = $this->getConfiguration()->getAttribute('em');
return $em->getConnection()->getSchemaManager();
// If source is annotation then lets try and find the existing annotation
// driver for the source instead of re-creating a new instance
} else if ($type == 'annotation') {
$em = $this->getConfiguration()->getAttribute('em');
$metadataDriverImpl = $em->getConfiguration()->getMetadataDriverImpl();
// Find the annotation driver in the chain of drivers
if ($metadataDriverImpl instanceof DriverChain) {
foreach ($metadataDriverImpl->getDrivers() as $namespace => $driver) {
if ($this->_isAnnotationDriverForPath($driver, $source)) {
return $driver;
}
}
} else if ($this->_isAnnotationDriverForPath($metadataDriverImpl, $source)) {
return $metadataDriverImpl;
} else {
return $source;
}
} else {
return $source;
}
}
/**
* Check to see if the given metadata driver is the annotation driver for the
* given directory path
*
* @param Driver $driver
* @param string $path
* @return boolean
*/
private function _isAnnotationDriverForPath(Driver $driver, $path)
{
if ( ! $driver instanceof AnnotationDriver) {
return false;
}
if (in_array(realpath($path), $driver->getPaths())) {
return true;
} else {
return false;
}
}
}
\ No newline at end of file
......@@ -26,7 +26,7 @@ use Doctrine\Common\Cli\Tasks\AbstractTask,
Doctrine\Common\Cli\OptionGroup,
Doctrine\Common\Cli\CliException,
Doctrine\ORM\Tools\EntityGenerator,
Doctrine\ORM\Tools\Export\ClassMetadataExporter;
Doctrine\ORM\Tools\ClassMetadataReader;
/**
* CLI Task to generate entity classes and method stubs from your mapping information.
......@@ -40,7 +40,7 @@ use Doctrine\Common\Cli\Tasks\AbstractTask,
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class GenerateEntitiesTask extends ConvertMappingTask
class GenerateEntitiesTask extends AbstractTask
{
/**
* @inheritdoc
......@@ -49,7 +49,7 @@ class GenerateEntitiesTask extends ConvertMappingTask
{
$options = new OptionGroup(OptionGroup::CARDINALITY_N_N, array(
new Option('from', '<FROM>', 'The path to mapping information.'),
new Option('dest', '<DEST>', 'The path to your entities.')
new Option('dest', '<DEST>', 'The path to generate your entity classes.')
));
$doc = $this->getDocumentation();
......@@ -65,7 +65,6 @@ class GenerateEntitiesTask extends ConvertMappingTask
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');
......@@ -74,6 +73,9 @@ class GenerateEntitiesTask extends ConvertMappingTask
return true;
}
/**
* @inheritdoc
*/
public function run()
{
$printer = $this->getPrinter();
......@@ -95,29 +97,24 @@ class GenerateEntitiesTask extends ConvertMappingTask
$generator->setNumSpaces($arguments['num-spaces']);
}
$type = $this->_determineSourceType($from);
$reader = new ClassMetadataReader();
$reader->setEntityManager($this->getConfiguration()->getAttribute('em'));
$reader->addMappingSource($from);
$metadatas = $reader->getMetadatas();
if ( ! $type) {
throw new CliException(
"Invalid mapping source type '$sourceArg'."
foreach ($metadatas as $metadata) {
$printer->writeln(
sprintf('Processing entity "%s"', $printer->format($metadata->name, 'KEYWORD'))
);
}
$source = $this->_getSourceByType($type, $from);
$cme = new ClassMetadataExporter();
$cme->addMappingSource($source, $type);
$metadatas = $cme->getMetadatasForMappingSources();
$generator->generate($metadatas, $dest);
$printer->writeln('');
$printer->writeln(
sprintf(
'Generating entity stubs for "%s" mapping information located at "%s" to "%s"',
$printer->format($type, 'KEYWORD'),
$printer->format($from, 'KEYWORD'),
sprintf('Entity classes generated to "%s"',
$printer->format($dest, 'KEYWORD')
)
);
$generator->generate($metadatas, $dest);
}
}
\ No newline at end of file
......@@ -87,13 +87,21 @@ class GenerateProxiesTask extends AbstractTask
if (empty($classes)) {
$printer->writeln('No classes to process.', 'INFO');
} else {
foreach ($classes as $class) {
$printer->writeln(
sprintf('Processing entity "%s"', $printer->format($class->name, 'KEYWORD'))
);
}
$factory->generateProxyClasses(
$classes, isset($arguments['to-dir']) ? $arguments['to-dir'] : null
);
$printer->writeln('');
$printer->writeln(
'Proxy classes generated to: ' . (isset($arguments['to-dir'])
? $arguments['to-dir'] : $em->getConfiguration()->getProxyDir())
sprintf('Proxy classes generated to "%s"',
$printer->format(isset($arguments['to-dir']) ? $arguments['to-dir'] : $em->getConfiguration()->getProxyDir(), 'KEYWORD'))
);
}
}
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
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\ClassMetadataReader;
/**
* CLI Task to generate repository classes for some 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 <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class GenerateRepositoriesTask extends ConvertMappingTask
{
private static $_template =
'<?php
namespace <namespace>;
use \Doctrine\ORM\EntityRepository;
/**
* <className>
*
* This class was generated by the Doctrine ORM. Add your own custom
* repository methods below.
*/
class <className> extends EntityRepository
{
}';
/**
* @inheritdoc
*/
public function buildDocumentation()
{
$options = new OptionGroup(OptionGroup::CARDINALITY_N_N, array(
new Option('from', '<FROM>', 'The path to mapping information.'),
new Option('dest', '<DEST>', 'The path to generate your repository classes.')
));
$doc = $this->getDocumentation();
$doc->setName('generate-repositories')
->setDescription('Generate repository classes for some 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();
$dest = realpath($arguments['dest']);
$reader = new ClassMetadataReader();
$reader->setEntityManager($this->getConfiguration()->getAttribute('em'));
$reader->addMappingSource($arguments['from']);
$metadatas = $reader->getMetadatas();
foreach ($metadatas as $metadata) {
if ($metadata->customRepositoryClassName) {
$code = $this->_generateRepositoryClass($metadata->customRepositoryClassName);
$path = $dest . '/' . str_replace('\\', '/', $metadata->customRepositoryClassName) . '.php';
$dir = dirname($path);
if ( ! is_dir($dir)) {
mkdir($dir, 0777, true);
}
$printer->writeln(
sprintf('Processing entity "%s"',
$printer->format($metadata->customRepositoryClassName, 'KEYWORD')
)
);
file_put_contents($path, $code);
}
}
$printer->writeln('');
$printer->writeln(
sprintf('Entity repository classes generated to "%s"',
$printer->format($dest, 'KEYWORD')
)
);
}
private function _generateRepositoryClass($fullyQualifiedClassName)
{
$namespace = substr($fullyQualifiedClassName, 0, strrpos($fullyQualifiedClassName, '\\'));
$pos = strrpos($fullyQualifiedClassName, '\\');
$className = substr($fullyQualifiedClassName, $pos + 1, strlen($fullyQualifiedClassName));
$placeHolders = array(
'<namespace>',
'<className>'
);
$replacements = array(
$namespace,
$className
);
$code = str_replace($placeHolders, $replacements, self::$_template);
return $code;
}
}
\ No newline at end of file
......@@ -62,7 +62,7 @@ class ConvertDoctrine1Schema
*
* @return array $metadatas An array of ClassMetadataInfo instances
*/
public function getMetadatasFromSchema()
public function getMetadatas()
{
$schema = array();
foreach ($this->_from as $path) {
......
......@@ -52,7 +52,7 @@ class EntityGenerator
private $_extension = '.php';
/** Whether or not the current ClassMetadataInfo instance is new or old */
private $_isNew;
private $_isNew = true;
/** If isNew is false then this variable contains instance of ReflectionClass for current entity */
private $_reflection;
......@@ -70,7 +70,7 @@ class EntityGenerator
private $_generateAnnotations = false;
/** Whether or not to generated sub methods */
private $_generateStubMethods = false;
private $_generateEntityStubMethods = false;
/** Whether or not to update the entity class if it exists already */
private $_updateEntityIfExists = false;
......@@ -254,7 +254,7 @@ class EntityGenerator
*/
public function setGenerateStubMethods($bool)
{
$this->_generateStubMethods = $bool;
$this->_generateEntityStubMethods = $bool;
}
private function _generateEntityNamespace(ClassMetadataInfo $metadata)
......@@ -281,7 +281,7 @@ class EntityGenerator
{
$fieldMappingProperties = $this->_generateEntityFieldMappingProperties($metadata);
$associationMappingProperties = $this->_generateEntityAssociationMappingProperties($metadata);
$stubMethods = $this->_generateStubMethods ? $this->_generateEntityStubMethods($metadata) : null;
$stubMethods = $this->_generateEntityStubMethods ? $this->_generateEntityStubMethods($metadata) : null;
$lifecycleCallbackMethods = $this->_generateEntityLifecycleCallbackMethods($metadata);
$code = '';
......@@ -448,45 +448,45 @@ class EntityGenerator
foreach ($metadata->fieldMappings as $fieldMapping) {
if ( ! isset($fieldMapping['id']) || ! $fieldMapping['id']) {
if ($code = $this->_generateStubMethod('set', $fieldMapping['fieldName'], $metadata)) {
if ($code = $this->_generateEntityStubMethod('set', $fieldMapping['fieldName'], $metadata)) {
$methods[] = $code;
}
}
if ($code = $this->_generateStubMethod('get', $fieldMapping['fieldName'], $metadata)) {
if ($code = $this->_generateEntityStubMethod('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)) {
if ($code = $this->_generateEntityStubMethod('set', $associationMapping->sourceFieldName, $metadata)) {
$methods[] = $code;
}
if ($code = $this->_generateStubMethod('get', $associationMapping->sourceFieldName, $metadata)) {
if ($code = $this->_generateEntityStubMethod('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)) {
if ($code = $this->_generateEntityStubMethod('set', $associationMapping->sourceFieldName, $metadata)) {
$methods[] = $code;
}
if ($code = $this->_generateStubMethod('get', $associationMapping->sourceFieldName, $metadata)) {
if ($code = $this->_generateEntityStubMethod('get', $associationMapping->sourceFieldName, $metadata)) {
$methods[] = $code;
}
} else {
if ($code = $this->_generateStubMethod('add', $associationMapping->sourceFieldName, $metadata)) {
if ($code = $this->_generateEntityStubMethod('add', $associationMapping->sourceFieldName, $metadata)) {
$methods[] = $code;
}
if ($code = $this->_generateStubMethod('get', $associationMapping->sourceFieldName, $metadata)) {
if ($code = $this->_generateEntityStubMethod('get', $associationMapping->sourceFieldName, $metadata)) {
$methods[] = $code;
}
}
} else if ($associationMapping instanceof \Doctrine\ORM\Mapping\ManyToManyMapping) {
if ($code = $this->_generateStubMethod('add', $associationMapping->sourceFieldName, $metadata)) {
if ($code = $this->_generateEntityStubMethod('add', $associationMapping->sourceFieldName, $metadata)) {
$methods[] = $code;
}
if ($code = $this->_generateStubMethod('get', $associationMapping->sourceFieldName, $metadata)) {
if ($code = $this->_generateEntityStubMethod('get', $associationMapping->sourceFieldName, $metadata)) {
$methods[] = $code;
}
}
......@@ -542,7 +542,7 @@ class EntityGenerator
return $code;
}
private function _generateStubMethod($type, $fieldName, ClassMetadataInfo $metadata)
private function _generateEntityStubMethod($type, $fieldName, ClassMetadataInfo $metadata)
{
$methodName = $type . ucfirst($fieldName);
if ($this->_hasMethod($methodName, $metadata)) {
......
......@@ -22,10 +22,8 @@
namespace Doctrine\ORM\Tools\Export;
use Doctrine\ORM\EntityManager,
Doctrine\ORM\Mapping\ClassMetadataInfo,
Doctrine\ORM\Mapping\ClassMetadata,
Doctrine\ORM\Mapping\MappingException;
use Doctrine\ORM\Tools\ClassMetadataReader,
Doctrine\ORM\EntityManager;
/**
* Class used for converting your mapping information between the
......@@ -36,14 +34,14 @@ use Doctrine\ORM\EntityManager,
* // and convert it to a single set of yaml files.
*
* $cme = new Doctrine\ORM\Tools\Export\ClassMetadataExporter();
* $cme->addMappingSource(__DIR__ . '/Entities', 'php');
* $cme->addMappingSource(__DIR__ . '/xml', 'xml');
* $cme->addMappingSource(__DIR__ . '/yaml', 'yaml');
* $cme->addMappingSource(__DIR__ . '/Entities');
* $cme->addMappingSource(__DIR__ . '/xml');
* $cme->addMappingSource(__DIR__ . '/yaml');
*
* $exporter = $cme->getExporter('yaml');
* $exporter->setOutputDir(__DIR__ . '/new_yaml');
*
* $exporter->setMetadatas($cme->getMetadatasForMappingSources());
* $exporter->setMetadatas($cme->getMetadatas());
* $exporter->export();
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
......@@ -54,7 +52,7 @@ use Doctrine\ORM\EntityManager,
*/
class ClassMetadataExporter
{
private $_exporterDrivers = array(
private static $_exporterDrivers = array(
'xml' => 'Doctrine\ORM\Tools\Export\Driver\XmlExporter',
'yaml' => 'Doctrine\ORM\Tools\Export\Driver\YamlExporter',
'yml' => 'Doctrine\ORM\Tools\Export\Driver\YamlExporter',
......@@ -62,85 +60,68 @@ class ClassMetadataExporter
'annotation' => 'Doctrine\ORM\Tools\Export\Driver\AnnotationExporter'
);
private $_mappingDrivers = array(
'annotation' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
'yaml' => 'Doctrine\ORM\Mapping\Driver\YamlDriver',
'yml' => 'Doctrine\ORM\Mapping\Driver\YamlDriver',
'xml' => 'Doctrine\ORM\Mapping\Driver\XmlDriver',
'php' => 'Doctrine\ORM\Mapping\Driver\PhpDriver',
'database' => 'Doctrine\ORM\Mapping\Driver\DatabaseDriver'
);
private $_mappingSources = array();
public function __construct()
{
$this->_reader = new ClassMetadataReader();
}
/**
* Add a new mapping directory to the array of directories to convert and export
* to another format
*
* [php]
* $cme = new Doctrine\ORM\Tools\Export\ClassMetadataExporter();
* $cme->addMappingSource(__DIR__ . '/yaml', 'yaml');
* $cme->addMappingSource($schemaManager, 'database');
* Register a new exporter driver class under a specified name
*
* @param string $source The source for the mapping
* @param string $type The type of mapping files (yml, xml, etc.)
* @return void
* @param string $name
* @param string $class
*/
public function addMappingSource($source, $type)
public static function registerExportDriver($name, $class)
{
if ( ! isset($this->_mappingDrivers[$type])) {
throw ExportException::invalidMappingDriverType($type);
}
$driver = $this->getMappingDriver($type, $source);
$this->_mappingSources[] = array($source, $driver);
self::$_exporterDrivers[$name] = $class;
}
/**
* Get an instance of a mapping driver
* Optionally set the EntityManager instance to get the AnnotationDriver
* from instead of creating a new instance of the AnnotationDriver
*
* @param string $type The type of mapping driver (yaml, xml, annotation, etc.)
* @param string $source The source for the driver
* @return AbstractDriver $driver
* @param EntityManager $em
* @return void
*/
public function getMappingDriver($type, $source = null)
public function setEntityManager(EntityManager $em)
{
if ($source instanceof \Doctrine\ORM\Mapping\Driver\Driver) {
return $source;
}
if ( ! isset($this->_mappingDrivers[$type])) {
return false;
$this->_reader->setEntityManager($em);
}
$class = $this->_mappingDrivers[$type];
if (is_subclass_of($class, 'Doctrine\ORM\Mapping\Driver\AbstractFileDriver')) {
if (is_null($source)) {
throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath();
/**
* Get a exporter driver instance
*
* @param string $type The type to get (yml, xml, etc.)
* @param string $source The directory where the exporter will export to
* @return AbstractExporter $exporter
*/
public function getExporter($type, $source = null)
{
if ( ! isset(self::$_exporterDrivers[$type])) {
throw ExportException::invalidExporterDriverType($type);
}
$driver = new $class($source);
} else if ($class == 'Doctrine\ORM\Mapping\Driver\AnnotationDriver') {
$reader = new \Doctrine\Common\Annotations\AnnotationReader(new \Doctrine\Common\Cache\ArrayCache);
$reader->setDefaultAnnotationNamespace('Doctrine\ORM\Mapping\\');
$driver = new \Doctrine\ORM\Mapping\Driver\AnnotationDriver($reader, $source);
} else {
$driver = new $class($source);
}
$class = self::$_exporterDrivers[$type];
return $driver;
return new $class($source);
}
/**
* Get the array of added mapping directories
* Add a new mapping directory to the array of directories to convert and export
* to another format
*
* @return array $mappingDirectories
* [php]
* $cme = new Doctrine\ORM\Tools\Export\ClassMetadataExporter();
* $cme->addMappingSource(__DIR__ . '/yaml');
* $cme->addMappingSource($schemaManager);
*
* @param string $source The source for the mapping files
* @param string $type The type of mapping files (yml, xml, etc.)
* @return void
*/
public function getMappingSources()
public function addMappingSource($source, $type = null)
{
return $this->_mappingSources;
$this->_reader->addMappingSource($source, $type);
}
/**
......@@ -150,48 +131,8 @@ class ClassMetadataExporter
*
* @return array $classes
*/
public function getMetadatasForMappingSources()
public function getMetadatas()
{
$classes = array();
foreach ($this->_mappingSources as $d) {
list($source, $driver) = $d;
$allClasses = $driver->getAllClassNames();
foreach ($allClasses as $className) {
if (class_exists($className, false)) {
$metadata = new ClassMetadata($className);
} else {
$metadata = new ClassMetadataInfo($className);
}
$driver->loadMetadataForClass($className, $metadata);
if ( ! $metadata->isMappedSuperclass) {
$classes[$metadata->name] = $metadata;
}
}
}
return $classes;
}
/**
* Get a exporter driver instance
*
* @param string $type The type to get (yml, xml, etc.)
* @param string $source The directory where the exporter will export to
* @return AbstractExporter $exporter
*/
public function getExporter($type, $source = null)
{
if ( ! isset($this->_exporterDrivers[$type])) {
throw ExportException::invalidExporterDriverType($type);
}
$class = $this->_exporterDrivers[$type];
return new $class($source);
return $this->_reader->getMetadatas();
}
}
\ No newline at end of file
......@@ -45,11 +45,31 @@ abstract class AbstractExporter
$this->_outputDir = $dir;
}
/**
* Converts a single ClassMetadata instance to the exported format
* and returns it
*
* @param ClassMetadataInfo $metadata
* @return mixed $exported
*/
abstract public function exportClassMetadata(ClassMetadataInfo $metadata);
/**
* Set the array of ClassMetadataInfo instances to export
*
* @param array $metadatas
* @return void
*/
public function setMetadatas(array $metadatas)
{
$this->_metadatas = $metadatas;
}
/**
* Get the extension used to generated the path to a class
*
* @return string $extension
*/
public function getExtension()
{
return $this->_extension;
......@@ -84,12 +104,27 @@ abstract class AbstractExporter
}
foreach ($this->_metadatas as $metadata) {
$outputPath = $this->_outputDir . '/' . str_replace('\\', '.', $metadata->name) . $this->_extension;
$output = $this->exportClassMetadata($metadata);
file_put_contents($outputPath, $output);
$path = $this->_generateOutputPath($metadata);
$dir = dirname($path);
if ( ! is_dir($dir)) {
mkdir($dir, 0777, true);
}
file_put_contents($path, $output);
}
}
/**
* Generate the path to write the class for the given ClassMetadataInfo instance
*
* @param ClassMetadataInfo $metadata
* @return string $path
*/
protected function _generateOutputPath(ClassMetadataInfo $metadata)
{
return $this->_outputDir . '/' . str_replace('\\', '.', $metadata->name) . $this->_extension;
}
/**
* Set the directory to output the mapping files to
*
......@@ -106,15 +141,6 @@ abstract class AbstractExporter
$this->_extension = $extension;
}
/**
* Converts a single ClassMetadata instance to the exported format
* and returns it
*
* @param ClassMetadataInfo $metadata
* @return mixed $exported
*/
abstract public function exportClassMetadata(ClassMetadataInfo $metadata);
protected function _getInheritanceTypeString($type)
{
switch ($type)
......
......@@ -59,7 +59,13 @@ class AnnotationExporter extends AbstractExporter
$this->_generator->setGenerateStubMethods(false);
$this->_generator->setRegenerateEntityIfExists(false);
$this->_generator->setUpdateEntityIfExists(false);
$this->_generator->writeEntityClass($metadata, $this->_outputDir);
return $this->_generator->generateEntityClass($metadata);
}
protected function _generateOutputPath(ClassMetadataInfo $metadata)
{
return $this->_outputDir . '/' . str_replace('\\', '/', $metadata->name) . $this->_extension;
}
/**
......
......@@ -89,9 +89,9 @@ class DatabaseDriverTest extends \Doctrine\Tests\OrmFunctionalTestCase
protected function extractClassMetadata($className)
{
$cm = new ClassMetadataExporter();
$cm->addMappingSource($this->_sm, 'database');
$cm->addMappingSource($this->_sm);
$exporter = $cm->getExporter('yaml');
$metadatas = $cm->getMetadatasForMappingSources();
$metadatas = $cm->getMetadatas();
$output = false;
......
......@@ -19,10 +19,10 @@ class PhpMappingDriverTest extends AbstractMappingDriverTest
// Uncomment this code if the YAML changes and you want to update the PHP code
// for the same mapping information
$cme = new ClassMetadataExporter();
$cme->addMappingSource(__DIR__ . DIRECTORY_SEPARATOR . 'yaml', 'yaml');
$cme->addMappingSource(__DIR__ . DIRECTORY_SEPARATOR . 'yaml');
$exporter = $cme->getExporter('php', $path);
$exporter->setMetadatas($cme->getMetadatasForMappingSources());
$exporter->setMetadatas($cme->getMetadatas());
$exporter->export();
*/
......
......@@ -44,14 +44,14 @@ class ConvertDoctrine1SchemaTest extends \Doctrine\Tests\OrmTestCase
$converter = new ConvertDoctrine1Schema(__DIR__ . '/doctrine1schema');
$exporter = $cme->getExporter('yml', __DIR__ . '/convert');
$exporter->setMetadatas($converter->getMetadatasFromSchema());
$exporter->setMetadatas($converter->getMetadatas());
$exporter->export();
$this->assertTrue(file_exists(__DIR__ . '/convert/User.dcm.yml'));
$this->assertTrue(file_exists(__DIR__ . '/convert/Profile.dcm.yml'));
$cme->addMappingSource(__DIR__ . '/convert', 'yml');
$metadatas = $cme->getMetadatasForMappingSources();
$cme->addMappingSource(__DIR__ . '/convert');
$metadatas = $cme->getMetadatas();
$this->assertEquals(2, count($metadatas));
$this->assertEquals('Profile', $metadatas['Profile']->name);
......
......@@ -65,7 +65,7 @@ abstract class AbstractClassMetadataExporterTest extends \Doctrine\Tests\OrmTest
{
$type = $this->_getType();
$cme = $this->_loadClassMetadataExporter();
$metadataInstances = $cme->getMetadatasForMappingSources();
$metadataInstances = $cme->getMetadatas();
$this->assertEquals('Doctrine\Tests\ORM\Tools\Export\User', $metadataInstances['Doctrine\Tests\ORM\Tools\Export\User']->name);
......@@ -81,7 +81,7 @@ abstract class AbstractClassMetadataExporterTest extends \Doctrine\Tests\OrmTest
$type = $this->_getType();
$exporter = $cme->getExporter($type, __DIR__ . '/export/' . $type);
$this->_extension = $exporter->getExtension();
$metadatas = $cme->getMetadatasForMappingSources();
$metadatas = $cme->getMetadatas();
if ($type == 'annotation') {
$metadatas['Doctrine\Tests\ORM\Tools\Export\User']->name = $this->_getTestEntityName();
}
......@@ -104,7 +104,8 @@ abstract class AbstractClassMetadataExporterTest extends \Doctrine\Tests\OrmTest
$type = $this->_getType();
$cme = new ClassMetadataExporter();
$cme->addMappingSource(__DIR__ . '/export/' . $type, $type);
$metadataInstances = $cme->getMetadatasForMappingSources();
$metadataInstances = $cme->getMetadatas();
$metadata = current($metadataInstances);
$this->assertEquals($this->_getTestEntityName(), $metadata->name);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment