From a7d4e1e4663e1f7b99c16648883b114051876ebe Mon Sep 17 00:00:00 2001 From: jwage Date: Wed, 7 Oct 2009 22:14:13 +0000 Subject: [PATCH] [2.0] Refactoring some common code in to the AnnotationDriver and creating PhpDriver for consistancy --- .../ORM/Mapping/Driver/AnnotationDriver.php | 37 +++++++- lib/Doctrine/ORM/Mapping/Driver/PhpDriver.php | 95 +++++++++++++++++++ .../Tools/Cli/Tasks/ConvertMappingTask.php | 19 ++-- .../ORM/Tools/Cli/Tasks/SchemaToolTask.php | 50 ++++------ .../Tools/Export/ClassMetadataExporter.php | 79 ++++----------- .../Tools/Export/Driver/AbstractExporter.php | 2 +- .../ORM/Tools/Export/Driver/PhpExporter.php | 1 - .../Export/ClassMetadataExporterTest.php | 2 +- tools/sandbox/cli-config.php | 2 +- 9 files changed, 176 insertions(+), 111 deletions(-) create mode 100644 lib/Doctrine/ORM/Mapping/Driver/PhpDriver.php diff --git a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php index dad972353..df60c1beb 100644 --- a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php +++ b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php @@ -44,18 +44,25 @@ class AnnotationDriver implements Driver { /** The AnnotationReader. */ private $_reader; - + private $_classDirectory; + /** * Initializes a new AnnotationDriver that uses the given AnnotationReader for reading * docblock annotations. * * @param AnnotationReader $reader The AnnotationReader to use. */ - public function __construct(AnnotationReader $reader) + public function __construct(AnnotationReader $reader, $classDirectory = null) { $this->_reader = $reader; + $this->_classDirectory = $classDirectory; } - + + public function setClassDirectory($classDirectory) + { + $this->_classDirectory = $classDirectory; + } + /** * {@inheritdoc} */ @@ -325,6 +332,28 @@ class AnnotationDriver implements Driver public function preload() { - return array(); + if ($this->_classDirectory) { + $iter = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->_classDirectory), + \RecursiveIteratorIterator::LEAVES_ONLY); + + $declared = get_declared_classes(); + foreach ($iter as $item) { + $info = pathinfo($item->getPathName()); + if (! isset($info['extension']) || $info['extension'] != 'php') { + continue; + } + require_once $item->getPathName(); + } + $declared = array_diff(get_declared_classes(), $declared); + + foreach ($declared as $className) { + if ( ! $this->isTransient($className)) { + $classes[] = $className; + } + } + return $classes; + } else { + return array(); + } } } \ No newline at end of file diff --git a/lib/Doctrine/ORM/Mapping/Driver/PhpDriver.php b/lib/Doctrine/ORM/Mapping/Driver/PhpDriver.php new file mode 100644 index 000000000..ee40b589f --- /dev/null +++ b/lib/Doctrine/ORM/Mapping/Driver/PhpDriver.php @@ -0,0 +1,95 @@ +. + */ + +namespace Doctrine\ORM\Mapping\Driver; + +use Doctrine\Common\DoctrineException, + Doctrine\Common\Cache\ArrayCache, + Doctrine\Common\Annotations\AnnotationReader, + Doctrine\DBAL\Schema\AbstractSchemaManager, + Doctrine\ORM\Mapping\ClassMetadataInfo, + Doctrine\ORM\Mapping\MappingException, + Doctrine\Common\Util\Inflector; + +/** + * The PhpDriver includes php files which just populate ClassMetadataInfo + * instances with plain php code + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class PhpDriver implements Driver +{ + /** The directory path to look in for php files */ + private $_directory; + + /** The array of class names found and the path to the file */ + private $_classPaths = array(); + + public function __construct($directory) + { + $this->_directory = $directory; + } + + public function loadMetadataForClass($className, ClassMetadataInfo $metadata) + { + $path = $this->_classPaths[$className]; + include $path; + } + + public function isTransient($className) + { + return true; + } + + /** + * Preloads all mapping information found in any documents within the + * configured paths and returns a list of class names that have been preloaded. + * + * @return array The list of class names that have been preloaded. + */ + public function preload() + { + if ( ! is_dir($this->_directory)) { + throw MappingException::phpDriverRequiresConfiguredDirectoryPath(); + } + $iter = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->_directory), + \RecursiveIteratorIterator::LEAVES_ONLY); + + $classes = array(); + foreach ($iter as $item) { + $info = pathinfo($item->getPathName()); + if (! isset($info['extension']) || $info['extension'] != 'php') { + continue; + } + $className = $info['filename']; + $classes[] = $className; + $this->_classPaths[$className] = $item->getPathName(); + } + + return $classes; + } +} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Tools/Cli/Tasks/ConvertMappingTask.php b/lib/Doctrine/ORM/Tools/Cli/Tasks/ConvertMappingTask.php index 48273e5af..d0cf8f4e8 100644 --- a/lib/Doctrine/ORM/Tools/Cli/Tasks/ConvertMappingTask.php +++ b/lib/Doctrine/ORM/Tools/Cli/Tasks/ConvertMappingTask.php @@ -21,7 +21,8 @@ namespace Doctrine\ORM\Tools\Cli\Tasks; -use Doctrine\ORM\Tools\Export\ClassMetadataExporter; +use Doctrine\ORM\Tools\Export\ClassMetadataExporter, + Doctrine\Common\DoctrineException; if ( ! class_exists('sfYaml', false)) { require_once __DIR__ . '/../../../../../vendor/sfYaml/sfYaml.class.php'; @@ -137,14 +138,17 @@ class ConvertMappingTask extends AbstractTask $sourceArg = $source; $type = $this->_determineSourceType($sourceArg); + if ( ! $type) { + throw DoctrineException::invalidMappingSourceType($sourceArg); + } $source = $this->_getSourceByType($type, $sourceArg); $printer->writeln( sprintf( - 'Adding "%s" mapping source', - $printer->format($sourceArg, 'KEYWORD') - ), - 'INFO' + 'Adding "%s" mapping source which contains the "%s" format', + $printer->format($sourceArg, 'KEYWORD'), + $printer->format($type, 'KEYWORD') + ) ); $cme->addMappingSource($source, $type); @@ -163,11 +167,10 @@ class ConvertMappingTask extends AbstractTask $printer->writeln( sprintf( - 'Exporting %s mapping information to directory "%s"', + 'Exporting "%s" mapping information to directory "%s"', $printer->format($args['to'], 'KEYWORD'), $printer->format($args['dest'], 'KEYWORD') - ), - 'INFO' + ) ); $exporter->setMetadatas($metadatas); diff --git a/lib/Doctrine/ORM/Tools/Cli/Tasks/SchemaToolTask.php b/lib/Doctrine/ORM/Tools/Cli/Tasks/SchemaToolTask.php index e81c7c46f..02f15b36d 100644 --- a/lib/Doctrine/ORM/Tools/Cli/Tasks/SchemaToolTask.php +++ b/lib/Doctrine/ORM/Tools/Cli/Tasks/SchemaToolTask.php @@ -14,7 +14,7 @@ use Doctrine\Common\DoctrineException, * * This task has the following arguments: * - * --classdir= + * --class-dir= * Specifies the directory where to start looking for mapped classes. * This argument is required when the annotation metadata driver is used, * otherwise it has no effect. @@ -71,7 +71,7 @@ class SchemaToolTask extends AbstractTask ->write('--dump-sql', 'OPT_ARG') ->writeln("\t\tInstead of try to apply generated SQLs into EntityManager, output them.") ->write(PHP_EOL) - ->write('--classdir=', 'OPT_ARG') + ->write('--class-dir=', 'OPT_ARG') ->writeln("\tOptional class directory to fetch for Entities."); } @@ -87,7 +87,7 @@ class SchemaToolTask extends AbstractTask { $printer->write('schema-tool', 'KEYWORD') ->write(' (--create | --drop | --update)', 'REQ_ARG') - ->writeln(' [--dump-sql] [--classdir=]', 'OPT_ARG'); + ->writeln(' [--dump-sql] [--class-dir=]', 'OPT_ARG'); } /** @@ -115,11 +115,15 @@ class SchemaToolTask extends AbstractTask return false; } - if ($this->_em->getConfiguration()->getMetadataDriverImpl() instanceof \Doctrine\ORM\Mapping\Driver\AnnotationDriver - && ! isset($args['classdir'])) { - $printer->writeln("The supplied configuration uses the annotation metadata driver." - . " The 'classdir' argument is required for this driver.", 'ERROR'); - return false; + $metadataDriver = $this->_em->getConfiguration()->getMetadataDriverImpl(); + if ($metadataDriver instanceof \Doctrine\ORM\Mapping\Driver\AnnotationDriver) { + if ( ! isset($args['class-dir'])) { + $printer->writeln("The supplied configuration uses the annotation metadata driver." + . " The 'class-dir' argument is required for this driver.", 'ERROR'); + return false; + } else { + $metadataDriver->setClassDirectory($args['class-dir']); + } } return true; @@ -140,33 +144,11 @@ class SchemaToolTask extends AbstractTask $driver = $this->_em->getConfiguration()->getMetadataDriverImpl(); $classes = array(); - - if ($driver instanceof \Doctrine\ORM\Mapping\Driver\AnnotationDriver) { - $iter = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($args['classdir']), - \RecursiveIteratorIterator::LEAVES_ONLY); - - $declared = get_declared_classes(); - foreach ($iter as $item) { - $info = pathinfo($item->getPathName()); - if (! isset($info['extension']) || $info['extension'] != 'php') { - continue; - } - require_once $item->getPathName(); - } - $declared = array_diff(get_declared_classes(), $declared); - - foreach ($declared as $className) { - if ( ! $driver->isTransient($className)) { - $classes[] = $cmf->getMetadataFor($className); - } - } - } else { - $preloadedClasses = $driver->preload(true); - foreach ($preloadedClasses as $className) { - $classes[] = $cmf->getMetadataFor($className); - } + $preloadedClasses = $driver->preload(true); + foreach ($preloadedClasses as $className) { + $classes[] = $cmf->getMetadataFor($className); } - + $printer = $this->getPrinter(); $tool = new SchemaTool($this->_em); diff --git a/lib/Doctrine/ORM/Tools/Export/ClassMetadataExporter.php b/lib/Doctrine/ORM/Tools/Export/ClassMetadataExporter.php index 48190e6e0..d3e938022 100644 --- a/lib/Doctrine/ORM/Tools/Export/ClassMetadataExporter.php +++ b/lib/Doctrine/ORM/Tools/Export/ClassMetadataExporter.php @@ -66,6 +66,7 @@ class ClassMetadataExporter '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' ); @@ -86,16 +87,12 @@ class ClassMetadataExporter */ public function addMappingSource($source, $type) { - if ($type === 'php') { - $this->_mappingSources[] = array($source, $type); - } else { - if ( ! isset($this->_mappingDrivers[$type])) { - throw DoctrineException::invalidMappingDriverType($type); - } - - $driver = $this->getMappingDriver($type, $source); - $this->_mappingSources[] = array($source, $driver); + if ( ! isset($this->_mappingDrivers[$type])) { + throw DoctrineException::invalidMappingDriverType($type); } + + $driver = $this->getMappingDriver($type, $source); + $this->_mappingSources[] = array($source, $driver); } /** @@ -119,9 +116,9 @@ class ClassMetadataExporter } 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); - } else if ($class == 'Doctrine\ORM\Mapping\Driver\DatabaseDriver') { - $driver = new \Doctrine\ORM\Mapping\Driver\DatabaseDriver($source); + $driver = new \Doctrine\ORM\Mapping\Driver\AnnotationDriver($reader, $source); + } else { + $driver = new $class($source); } return $driver; } @@ -149,61 +146,21 @@ class ClassMetadataExporter foreach ($this->_mappingSources as $d) { list($source, $driver) = $d; - if ($driver == 'php') { - $iter = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($source), - \RecursiveIteratorIterator::LEAVES_ONLY); - foreach ($iter as $item) { - $info = pathinfo($item->getPathName()); - if (! isset($info['extension']) || $info['extension'] != 'php') { - continue; - } - include $item->getPathName(); - $vars = get_defined_vars(); - foreach ($vars as $var) { - if ($var instanceof \Doctrine\ORM\Mapping\ClassMetadataInfo) { - $classes[$var->name] = $var; - } - } - } - } else { - if ($driver instanceof \Doctrine\ORM\Mapping\Driver\AnnotationDriver) { - $iter = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($source), - \RecursiveIteratorIterator::LEAVES_ONLY); - - $declared = get_declared_classes(); - foreach ($iter as $item) { - $info = pathinfo($item->getPathName()); - if (! isset($info['extension']) || $info['extension'] != 'php') { - continue; - } - require_once $item->getPathName(); - } - $declared = array_diff(get_declared_classes(), $declared); - - foreach ($declared as $className) { - if ( ! $driver->isTransient($className)) { - $metadata = new ClassMetadata($className); - $driver->loadMetadataForClass($className, $metadata); - $classes[$metadata->name] = $metadata; - } - } + $preloadedClasses = $driver->preload(true); + foreach ($preloadedClasses as $className) { + if (class_exists($className, false)) { + $metadata = new ClassMetadata($className); } else { - $preloadedClasses = $driver->preload(true); - foreach ($preloadedClasses as $className) { - $metadata = new ClassMetadataInfo($className); - $driver->loadMetadataForClass($className, $metadata); - $classes[$metadata->name] = $metadata; - } + $metadata = new ClassMetadataInfo($className); + } + $driver->loadMetadataForClass($className, $metadata); + if ( ! $metadata->isMappedSuperclass) { + $classes[$metadata->name] = $metadata; } } } - foreach ($classes as $key => $class) { - if ($class->isMappedSuperclass) { - unset($classes[$key]); - } - } return $classes; } diff --git a/lib/Doctrine/ORM/Tools/Export/Driver/AbstractExporter.php b/lib/Doctrine/ORM/Tools/Export/Driver/AbstractExporter.php index b8321ec44..6f84e8237 100644 --- a/lib/Doctrine/ORM/Tools/Export/Driver/AbstractExporter.php +++ b/lib/Doctrine/ORM/Tools/Export/Driver/AbstractExporter.php @@ -84,7 +84,7 @@ abstract class AbstractExporter } foreach ($this->_metadatas as $metadata) { - $outputPath = $this->_outputDir . '/' . str_replace('\\', '.', $metadata->name) . $this->_extension; + $outputPath = $this->_outputDir . '/' . $metadata->name . $this->_extension; $output = $this->exportClassMetadata($metadata); file_put_contents($outputPath, $output); } diff --git a/lib/Doctrine/ORM/Tools/Export/Driver/PhpExporter.php b/lib/Doctrine/ORM/Tools/Export/Driver/PhpExporter.php index bcd7f7e97..1d0e62642 100644 --- a/lib/Doctrine/ORM/Tools/Export/Driver/PhpExporter.php +++ b/lib/Doctrine/ORM/Tools/Export/Driver/PhpExporter.php @@ -51,7 +51,6 @@ class PhpExporter extends AbstractExporter $lines[] = null; $lines[] = 'use Doctrine\ORM\Mapping\ClassMetadataInfo;'; $lines[] = null; - $lines[] = "\$metadata = new ClassMetadataInfo('" . $metadata->name . "');"; if ($metadata->isMappedSuperclass) { $lines[] = '$metadata->isMappedSuperclass = true;'; diff --git a/tests/Doctrine/Tests/ORM/Tools/Export/ClassMetadataExporterTest.php b/tests/Doctrine/Tests/ORM/Tools/Export/ClassMetadataExporterTest.php index 660b4161d..bd1dd9651 100644 --- a/tests/Doctrine/Tests/ORM/Tools/Export/ClassMetadataExporterTest.php +++ b/tests/Doctrine/Tests/ORM/Tools/Export/ClassMetadataExporterTest.php @@ -73,7 +73,7 @@ class ClassMetadataExporterTest extends \Doctrine\Tests\OrmTestCase $this->assertTrue($mappingSources[0][1] instanceof \Doctrine\ORM\Mapping\Driver\AnnotationDriver); $this->assertEquals($mappingSources[1][0], __DIR__.'/php'); - $this->assertEquals('php', $mappingSources[1][1]); + $this->assertTrue($mappingSources[1][1] instanceof \Doctrine\ORM\Mapping\Driver\PhpDriver); $this->assertEquals($mappingSources[2][0], __DIR__.'/xml'); $this->assertTrue($mappingSources[2][1] instanceof \Doctrine\ORM\Mapping\Driver\XmlDriver); diff --git a/tools/sandbox/cli-config.php b/tools/sandbox/cli-config.php index ff19f1b03..c7c0c4c9f 100644 --- a/tools/sandbox/cli-config.php +++ b/tools/sandbox/cli-config.php @@ -29,5 +29,5 @@ $connectionOptions = array( $em = \Doctrine\ORM\EntityManager::create($connectionOptions, $config); $args = array( - 'classdir' => './Entities' + 'class-dir' => './Entities' ); \ No newline at end of file