diff --git a/UPGRADE_TO_2_0 b/UPGRADE_TO_2_0 index 379d364db..edd11e965 100644 --- a/UPGRADE_TO_2_0 +++ b/UPGRADE_TO_2_0 @@ -1,6 +1,62 @@ # Upgrade from 2.0-ALPHA4 to 2.0-BETA1 +## Console migrated to Symfony Console + +The Doctrine Cli has been replaced by Symfony Console Configuration + +Instead of having to specifiy: + + [php] + $cliConfig = new CliConfiguration(); + $cliConfig->setAttribute('em', $entityManager); + +You now have to configure the script like: + + [php] + $helperSet = new \Symfony\Components\Console\Helper\HelperSet(array( + 'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($em->getConnection()), + 'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em) + )); + +## Console: No need for Mapping Paths anymore + +In previous versions you had to specify the --from and --from-path options +to show where your mapping paths are from the console. However this information +is already known from the Mapping Driver configuration, so the requirement +for this options were dropped. + +Instead for each console command all the entities are loaded and to +restrict the operation to one or more sub-groups you can use the --filter flag. + +## AnnotationDriver is not a default mapping driver anymore + +In conjunction with the recent changes to Console we realized that the +annotations driver being a default metadata driver lead to lots of glue +code in the console components to detect where entities lie and how to load +them for batch updates like SchemaTool and other commands. However the +annotations driver being a default driver does not really help that much +anyways. + +Therefore we decided to break backwards compability in this issue and drop +the support for Annotations as Default Driver and require our users to +specify the driver explicitly (which allows us to ask for the path to all +entities). + +If you are using the annotations metadata driver as default driver, you +have to add the following lines to your bootstrap code: + + $driverImpl = $config->newDefaultAnnotationDriver(array(__DIR__."/Entities")); + $config->setMetadataDriverImpl($driverImpl); + +You have to specify the path to your entities as either string of a single +path or array of multiple paths +to your entities. This information will be used by all console commands to +access all entities. + +Xml and Yaml Drivers work as before! + + ## New inversedBy attribute It is now *mandatory* that the owning side of a bidirectional association specifies the diff --git a/lib/Doctrine/ORM/Configuration.php b/lib/Doctrine/ORM/Configuration.php index 4e7a37e5c..609bbfcd1 100644 --- a/lib/Doctrine/ORM/Configuration.php +++ b/lib/Doctrine/ORM/Configuration.php @@ -19,6 +19,9 @@ namespace Doctrine\ORM; +use Doctrine\Common\Cache\Cache, + Doctrine\ORM\Mapping\Driver\Driver; + /** * Configuration container for all configuration options of Doctrine. * It combines all configuration options from DBAL & ORM. @@ -116,15 +119,29 @@ class Configuration extends \Doctrine\DBAL\Configuration /** * Sets the cache driver implementation that is used for metadata caching. * - * @param object $driverImpl + * @param Driver $driverImpl * @todo Force parameter to be a Closure to ensure lazy evaluation * (as soon as a metadata cache is in effect, the driver never needs to initialize). */ - public function setMetadataDriverImpl($driverImpl) + public function setMetadataDriverImpl(Driver $driverImpl) { $this->_attributes['metadataDriverImpl'] = $driverImpl; } + /** + * Add a new default annotation driver with a correctly configured annotation reader. + * + * @param array $paths + * @return Mapping\Driver\AnnotationDriver + */ + public function newDefaultAnnotationDriver($paths = array()) + { + $reader = new \Doctrine\Common\Annotations\AnnotationReader(); + $reader->setDefaultAnnotationNamespace('Doctrine\ORM\Mapping\\'); + + return new \Doctrine\ORM\Mapping\Driver\AnnotationDriver($reader, (array)$paths); + } + /** * Adds a namespace under a certain alias. * @@ -166,23 +183,18 @@ class Configuration extends \Doctrine\DBAL\Configuration /** * Gets the cache driver implementation that is used for the mapping metadata. * - * @return object + * @throws ORMException + * @return Mapping\Driver\Driver */ public function getMetadataDriverImpl() { - if ($this->_attributes['metadataDriverImpl'] == null) { - $reader = new \Doctrine\Common\Annotations\AnnotationReader(new \Doctrine\Common\Cache\ArrayCache); - $reader->setDefaultAnnotationNamespace('Doctrine\ORM\Mapping\\'); - $this->_attributes['metadataDriverImpl'] = new \Doctrine\ORM\Mapping\Driver\AnnotationDriver($reader); - } - return $this->_attributes['metadataDriverImpl']; } /** * Gets the cache driver implementation that is used for query result caching. * - * @return object + * @return \Doctrine\Common\Cache\Cache */ public function getResultCacheImpl() { @@ -192,9 +204,9 @@ class Configuration extends \Doctrine\DBAL\Configuration /** * Sets the cache driver implementation that is used for query result caching. * - * @param object $cacheImpl + * @param \Doctrine\Common\Cache\Cache $cacheImpl */ - public function setResultCacheImpl($cacheImpl) + public function setResultCacheImpl(Cache $cacheImpl) { $this->_attributes['resultCacheImpl'] = $cacheImpl; } @@ -202,7 +214,7 @@ class Configuration extends \Doctrine\DBAL\Configuration /** * Gets the cache driver implementation that is used for the query cache (SQL cache). * - * @return object + * @return \Doctrine\Common\Cache\Cache */ public function getQueryCacheImpl() { @@ -212,9 +224,9 @@ class Configuration extends \Doctrine\DBAL\Configuration /** * Sets the cache driver implementation that is used for the query cache (SQL cache). * - * @param object $cacheImpl + * @param \Doctrine\Common\Cache\Cache $cacheImpl */ - public function setQueryCacheImpl($cacheImpl) + public function setQueryCacheImpl(Cache $cacheImpl) { $this->_attributes['queryCacheImpl'] = $cacheImpl; } @@ -222,7 +234,7 @@ class Configuration extends \Doctrine\DBAL\Configuration /** * Gets the cache driver implementation that is used for metadata caching. * - * @return object + * @return \Doctrine\Common\Cache\Cache */ public function getMetadataCacheImpl() { @@ -232,9 +244,9 @@ class Configuration extends \Doctrine\DBAL\Configuration /** * Sets the cache driver implementation that is used for metadata caching. * - * @param object $cacheImpl + * @param \Doctrine\Common\Cache\Cache $cacheImpl */ - public function setMetadataCacheImpl($cacheImpl) + public function setMetadataCacheImpl(Cache $cacheImpl) { $this->_attributes['metadataCacheImpl'] = $cacheImpl; } diff --git a/lib/Doctrine/ORM/EntityManager.php b/lib/Doctrine/ORM/EntityManager.php index 897569b8c..e2db2b0d0 100644 --- a/lib/Doctrine/ORM/EntityManager.php +++ b/lib/Doctrine/ORM/EntityManager.php @@ -593,9 +593,11 @@ class EntityManager * @param EventManager $eventManager The EventManager instance to use. * @return EntityManager The created EntityManager. */ - public static function create($conn, Configuration $config = null, EventManager $eventManager = null) + public static function create($conn, Configuration $config, EventManager $eventManager = null) { - $config = $config ?: new Configuration(); + if (!$config->getMetadataDriverImpl()) { + throw ORMException::missingMappingDriverImpl(); + } if (is_array($conn)) { $conn = \Doctrine\DBAL\DriverManager::getConnection($conn, $config, ($eventManager ?: new EventManager())); diff --git a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php index 8e01479f7..ec3d92f7b 100644 --- a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php +++ b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php @@ -428,40 +428,41 @@ class AnnotationDriver implements Driver return $this->_classNames; } + if (!$this->_paths) { + throw MappingException::pathRequired(); + } + $classes = array(); + $includedFiles = array(); - if ($this->_paths) { - $includedFiles = array(); - - foreach ((array) $this->_paths as $path) { - if ( ! is_dir($path)) { - throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath(); - } - - $iterator = new \RecursiveIteratorIterator( - new \RecursiveDirectoryIterator($path), - \RecursiveIteratorIterator::LEAVES_ONLY - ); - - foreach ($iterator as $file) { - if (($fileName = $file->getBasename($this->_fileExtension)) == $file->getBasename()) { - continue; - } - - $sourceFile = realpath($file->getPathName()); - require_once $sourceFile; - $includedFiles[] = $sourceFile; - } + foreach ($this->_paths as $path) { + if ( ! is_dir($path)) { + throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath(); } - $declared = get_declared_classes(); + $iterator = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($path), + \RecursiveIteratorIterator::LEAVES_ONLY + ); - foreach ($declared as $className) { - $rc = new \ReflectionClass($className); - $sourceFile = $rc->getFileName(); - if (in_array($sourceFile, $includedFiles) && ! $this->isTransient($className)) { - $classes[] = $className; + foreach ($iterator as $file) { + if (($fileName = $file->getBasename($this->_fileExtension)) == $file->getBasename()) { + continue; } + + $sourceFile = realpath($file->getPathName()); + require_once $sourceFile; + $includedFiles[] = $sourceFile; + } + } + + $declared = get_declared_classes(); + + foreach ($declared as $className) { + $rc = new \ReflectionClass($className); + $sourceFile = $rc->getFileName(); + if (in_array($sourceFile, $includedFiles) && ! $this->isTransient($className)) { + $classes[] = $className; } } @@ -470,4 +471,19 @@ class AnnotationDriver implements Driver return $classes; } + /** + * Factory method for the Annotation Driver + * + * @param array|string $paths + * @param AnnotationReader $reader + * @return AnnotationDriver + */ + static public function create($paths = array(), AnnotationReader $reader = null) + { + if ($reader == null) { + $reader = new AnnotationReader(); + $reader->setDefaultAnnotationNamespace('Doctrine\ORM\Mapping\\'); + } + return new self($reader, $paths); + } } diff --git a/lib/Doctrine/ORM/Mapping/MappingException.php b/lib/Doctrine/ORM/Mapping/MappingException.php index ae0907728..8881a3c71 100644 --- a/lib/Doctrine/ORM/Mapping/MappingException.php +++ b/lib/Doctrine/ORM/Mapping/MappingException.php @@ -28,6 +28,12 @@ namespace Doctrine\ORM\Mapping; */ class MappingException extends \Doctrine\ORM\ORMException { + public static function pathRequired() + { + return new self("Specifying the paths to your entities is required ". + "in the AnnotationDriver to retrieve all class names."); + } + public static function identifierRequired($entityName) { return new self("No identifier/primary key specified for Entity '$entityName'." diff --git a/lib/Doctrine/ORM/ORMException.php b/lib/Doctrine/ORM/ORMException.php index 82a8a877e..4d39d1e47 100644 --- a/lib/Doctrine/ORM/ORMException.php +++ b/lib/Doctrine/ORM/ORMException.php @@ -10,6 +10,12 @@ namespace Doctrine\ORM; */ class ORMException extends \Exception { + public static function missingMappingDriverImpl() + { + return new self("It's a requirement to specify a Metadata Driver and pass it ". + "to Doctrine\ORM\Configuration::setMetadataDriverImpl()."); + } + public static function entityMissingAssignedId($entity) { return new self("Entity of type " . get_class($entity) . " is missing an assigned ID."); diff --git a/lib/Doctrine/ORM/Tools/Console/Command/ConvertDoctrine1SchemaCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/ConvertDoctrine1SchemaCommand.php index 48ce45fb0..ae297c84f 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/ConvertDoctrine1SchemaCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/ConvertDoctrine1SchemaCommand.php @@ -23,7 +23,9 @@ namespace Doctrine\ORM\Tools\Console\Command; use Symfony\Components\Console\Input\InputArgument, Symfony\Components\Console\Input\InputOption, - Symfony\Components\Console; + Symfony\Components\Console, + Doctrine\ORM\Tools\Export\ClassMetadataExporter, + Doctrine\ORM\Tools\ConvertDoctrine1Schema; /** * Command to convert a Doctrine 1 schema to a Doctrine 2 mapping file. diff --git a/lib/Doctrine/ORM/Tools/Console/Command/ConvertMappingCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/ConvertMappingCommand.php index 45bc79714..48e6f3eb2 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/ConvertMappingCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/ConvertMappingCommand.php @@ -23,7 +23,9 @@ namespace Doctrine\ORM\Tools\Console\Command; use Symfony\Components\Console\Input\InputArgument, Symfony\Components\Console\Input\InputOption, - Symfony\Components\Console; + Symfony\Components\Console, + Doctrine\ORM\Tools\Console\MetadataFilter, + Doctrine\ORM\Tools\Export\ClassMetadataExporter; /** * Command to convert your mapping information between the various formats. @@ -48,8 +50,9 @@ class ConvertMappingCommand extends Console\Command\Command ->setName('orm:convert-mapping') ->setDescription('Convert mapping information between supported formats.') ->setDefinition(array( - new InputArgument( - 'from-path', InputArgument::REQUIRED, 'The path of mapping information.' + new InputOption( + 'filter', null, InputOption::PARAMETER_REQUIRED | InputOption::PARAMETER_IS_ARRAY, + 'A string pattern used to match entities that should be processed.' ), new InputArgument( 'to-type', InputArgument::REQUIRED, 'The mapping type to be converted.' @@ -58,10 +61,8 @@ class ConvertMappingCommand extends Console\Command\Command 'dest-path', InputArgument::REQUIRED, 'The path to generate your entities classes.' ), - new InputOption( - 'from', null, InputOption::PARAMETER_REQUIRED | InputOption::PARAMETER_IS_ARRAY, - 'Optional paths of mapping information.', - array() + new InputArgument( + 'from-database', InputArgument::OPTIONAL, 'The path of mapping information.' ), new InputOption( 'extend', null, InputOption::PARAMETER_OPTIONAL, @@ -84,37 +85,16 @@ EOT protected function execute(Console\Input\InputInterface $input, Console\Output\OutputInterface $output) { $em = $this->getHelper('em')->getEntityManager(); - $cme = new ClassMetadataExporter(); - // Process source directories - $fromPath = $input->getArgument('from-path'); + $metadatas = $em->getMetadataFactory()->getAllMetadata(); + $metadatas = MetadataFilter::filter($metadatas, $input->getOption('filter')); - if (strtolower($fromPath) !== 'database') { - $fromPaths = array_merge(array($fromPath), $input->getOption('from')); - - foreach ($fromPaths as &$dirName) { - $dirName = realpath($dirName); - - if ( ! file_exists($dirName)) { - throw new \InvalidArgumentException( - sprintf("Mapping directory '%s' does not exist.", $dirName) - ); - } else if ( ! is_readable($dirName)) { - throw new \InvalidArgumentException( - sprintf("Mapping directory '%s' does not have read permissions.", $dirName) - ); - } - - $cme->addMappingSource($dirName); - } - } else { + if ($input->getArgument('from-database') === true) { $em->getConfiguration()->setMetadataDriverImpl( new \Doctrine\ORM\Mapping\Driver\DatabaseDriver( $em->getConnection()->getSchemaManager() ) ); - - $cme->addMappingSource($fromPath); } // Process destination directory @@ -132,6 +112,7 @@ EOT $toType = strtolower($input->getArgument('to-type')); + $cme = new ClassMetadataExporter(); $exporter = $cme->getExporter($toType, $destPath); if ($toType == 'annotation') { @@ -145,9 +126,7 @@ EOT } } - $metadatas = $cme->getMetadatas(); - - if ($metadatas) { + if (count($metadatas)) { foreach ($metadatas as $metadata) { $output->write(sprintf('Processing entity "%s"', $metadata->name) . PHP_EOL); } @@ -156,7 +135,7 @@ EOT $exporter->export(); $output->write(PHP_EOL . sprintf( - 'Exporting "%s" mapping information to "%s"', $toType, $destPath + 'Exporting "%s" mapping information to "%s"' . PHP_EOL, $toType, $destPath )); } else { $output->write('No Metadata Classes to process.' . PHP_EOL); diff --git a/lib/Doctrine/ORM/Tools/Console/Command/GenerateEntitiesCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/GenerateEntitiesCommand.php index 0cf0230dd..119a08c1b 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/GenerateEntitiesCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/GenerateEntitiesCommand.php @@ -23,7 +23,9 @@ namespace Doctrine\ORM\Tools\Console\Command; use Symfony\Components\Console\Input\InputArgument, Symfony\Components\Console\Input\InputOption, - Symfony\Components\Console; + Symfony\Components\Console, + Doctrine\ORM\Tools\Console\MetadataFilter, + Doctrine\ORM\Tools\EntityGenerator; /** * Command to generate entity classes and method stubs from your mapping information. @@ -48,17 +50,13 @@ class GenerateEntitiesCommand extends Console\Command\Command ->setName('orm:generate-entities') ->setDescription('Generate entity classes and method stubs from your mapping information.') ->setDefinition(array( - new InputArgument( - 'from-path', InputArgument::REQUIRED, 'The path of mapping information.' + new InputOption( + 'filter', null, InputOption::PARAMETER_REQUIRED | InputOption::PARAMETER_IS_ARRAY, + 'A string pattern used to match entities that should be processed.' ), new InputArgument( 'dest-path', InputArgument::REQUIRED, 'The path to generate your entity classes.' ), - new InputOption( - 'from', null, InputOption::PARAMETER_REQUIRED | InputOption::PARAMETER_IS_ARRAY, - 'Optional paths of mapping information.', - array() - ), new InputOption( 'generate-annotations', null, InputOption::PARAMETER_OPTIONAL, 'Flag to define if generator should generate annotation metadata on entities.', false @@ -96,29 +94,10 @@ EOT protected function execute(Console\Input\InputInterface $input, Console\Output\OutputInterface $output) { $em = $this->getHelper('em')->getEntityManager(); - - $reader = new ClassMetadataReader(); - $reader->setEntityManager($em); - - // Process source directories - $fromPaths = array_merge(array($input->getArgument('from-path')), $input->getOption('from')); - - foreach ($fromPaths as $dirName) { - $dirName = realpath($dirName); - - if ( ! file_exists($dirName)) { - throw new \InvalidArgumentException( - sprintf("Mapping directory '%s' does not exist.", $dirName) - ); - } else if ( ! is_readable($dirName)) { - throw new \InvalidArgumentException( - sprintf("Mapping directory '%s' does not have read permissions.", $dirName) - ); - } - - $reader->addMappingSource($dirName); - } - + + $metadatas = $em->getMetadataFactory()->getAllMetadata(); + $metadatas = MetadataFilter::filter($metadatas, $input->getOption('filter')); + // Process destination directory $destPath = realpath($input->getArgument('dest-path')); @@ -132,23 +111,20 @@ EOT ); } - // Create EntityGenerator - $entityGenerator = new EntityGenerator(); + if ( count($metadatas)) { + // Create EntityGenerator + $entityGenerator = new EntityGenerator(); - $entityGenerator->setGenerateAnnotations($input->getOption('generate-annotations')); - $entityGenerator->setGenerateStubMethods($input->getOption('generate-methods')); - $entityGenerator->setRegenerateEntityIfExists($input->getOption('regenerate-entities')); - $entityGenerator->setUpdateEntityIfExists($input->getOption('update-entities')); - $entityGenerator->setNumSpaces($input->getOption('num-spaces')); + $entityGenerator->setGenerateAnnotations($input->getOption('generate-annotations')); + $entityGenerator->setGenerateStubMethods($input->getOption('generate-methods')); + $entityGenerator->setRegenerateEntityIfExists($input->getOption('regenerate-entities')); + $entityGenerator->setUpdateEntityIfExists($input->getOption('update-entities')); + $entityGenerator->setNumSpaces($input->getOption('num-spaces')); - if (($extend = $input->getOption('extend')) !== null) { - $entityGenerator->setClassToExtend($extend); - } + if (($extend = $input->getOption('extend')) !== null) { + $entityGenerator->setClassToExtend($extend); + } - // Retrieving ClassMetadatas - $metadatas = $reader->getMetadatas(); - - if ( ! empty($metadatas)) { foreach ($metadatas as $metadata) { $output->write( sprintf('Processing entity "%s"', $metadata->name) . PHP_EOL diff --git a/lib/Doctrine/ORM/Tools/Console/Command/GenerateProxiesCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/GenerateProxiesCommand.php index 4b6333b6f..5f71125d0 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/GenerateProxiesCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/GenerateProxiesCommand.php @@ -23,7 +23,8 @@ namespace Doctrine\ORM\Tools\Console\Command; use Symfony\Components\Console\Input\InputArgument, Symfony\Components\Console\Input\InputOption, - Symfony\Components\Console; + Symfony\Components\Console, + Doctrine\ORM\Tools\Console\MetadataFilter; /** * Command to (re)generate the proxy classes used by doctrine. @@ -48,18 +49,14 @@ class GenerateProxiesCommand extends Console\Command\Command ->setName('orm:generate-proxies') ->setDescription('Generates proxy classes for entity classes.') ->setDefinition(array( - new InputArgument( - 'from-path', InputArgument::REQUIRED, 'The path of mapping information.' + new InputOption( + 'filter', null, InputOption::PARAMETER_REQUIRED | InputOption::PARAMETER_IS_ARRAY, + 'A string pattern used to match entities that should be processed.' ), new InputArgument( 'dest-path', InputArgument::OPTIONAL, 'The path to generate your proxy classes. If none is provided, it will attempt to grab from configuration.' ), - new InputOption( - 'from', null, InputOption::PARAMETER_REQUIRED | InputOption::PARAMETER_IS_ARRAY, - 'Optional paths of mapping information.', - array() - ) )) ->setHelp(<<getHelper('em')->getEntityManager(); - - $reader = new ClassMetadataReader(); - $reader->setEntityManager($em); - - // Process source directories - $fromPaths = array_merge(array($input->getArgument('from-path')), $input->getOption('from')); - - foreach ($fromPaths as $dirName) { - $dirName = realpath($dirName); - - if ( ! file_exists($dirName)) { - throw new \InvalidArgumentException( - sprintf("Mapping directory '%s' does not exist.", $dirName) - ); - } else if ( ! is_readable($dirName)) { - throw new \InvalidArgumentException( - sprintf("Mapping directory '%s' does not have read permissions.", $dirName) - ); - } - - $reader->addMappingSource($dirName); - } + + $metadatas = $em->getMetadataFactory()->getAllMetadata(); + $metadatas = MetadataFilter::filter($metadatas, $input->getOption('filter')); // Process destination directory if (($destPath = $input->getArgument('dest-path')) === null) { @@ -113,10 +91,7 @@ EOT ); } - // Retrieving ClassMetadatas - $metadatas = $reader->getMetadatas(); - - if ( ! empty($metadatas)) { + if ( count($metadatas)) { foreach ($metadatas as $metadata) { $output->write( sprintf('Processing entity "%s"', $metadata->name) . PHP_EOL diff --git a/lib/Doctrine/ORM/Tools/Console/Command/GenerateRepositoriesCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/GenerateRepositoriesCommand.php index 1d24fccb3..9c1477fcd 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/GenerateRepositoriesCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/GenerateRepositoriesCommand.php @@ -23,7 +23,8 @@ namespace Doctrine\ORM\Tools\Console\Command; use Symfony\Components\Console\Input\InputArgument, Symfony\Components\Console\Input\InputOption, - Symfony\Components\Console; + Symfony\Components\Console, + Doctrine\ORM\Tools\Console\MetadataFilter; /** * Command to generate repository classes for mapping information. @@ -65,16 +66,12 @@ class extends EntityRepository ->setName('orm:generate-repositories') ->setDescription('Generate repository classes from your mapping information.') ->setDefinition(array( - new InputArgument( - 'from-path', InputArgument::REQUIRED, 'The path of mapping information.' + new InputOption( + 'filter', null, InputOption::PARAMETER_REQUIRED | InputOption::PARAMETER_IS_ARRAY, + 'A string pattern used to match entities that should be processed.' ), new InputArgument( 'dest-path', InputArgument::REQUIRED, 'The path to generate your repository classes.' - ), - new InputOption( - 'from', null, InputOption::PARAMETER_REQUIRED | InputOption::PARAMETER_IS_ARRAY, - 'Optional paths of mapping information.', - array() ) )) ->setHelp(<<getHelper('em')->getEntityManager(); - - $reader = new ClassMetadataReader(); - $reader->setEntityManager($em); - - // Process source directories - $fromPaths = array_merge(array($input->getArgument('from-path')), $input->getOption('from')); - - foreach ($fromPaths as $dirName) { - $dirName = realpath($dirName); - - if ( ! file_exists($dirName)) { - throw new \InvalidArgumentException( - sprintf("Mapping directory '%s' does not exist.", $dirName) - ); - } else if ( ! is_readable($dirName)) { - throw new \InvalidArgumentException( - sprintf("Mapping directory '%s' does not have read permissions.", $dirName) - ); - } - - $reader->addMappingSource($dirName); - } + + $metadatas = $em->getMetadataFactory()->getAllMetadata(); + $metadatas = MetadataFilter::filter($metadatas, $input->getOption('filter')); // Process destination directory $destPath = realpath($input->getArgument('dest-path')); @@ -125,10 +103,7 @@ EOT ); } - // Retrieving ClassMetadatas - $metadatas = $reader->getMetadatas(); - - if ( ! empty($metadatas)) { + if ( count($metadatas)) { $numRepositories = 0; foreach ($metadatas as $metadata) { diff --git a/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/AbstractCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/AbstractCommand.php new file mode 100644 index 000000000..84267fbd7 --- /dev/null +++ b/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/AbstractCommand.php @@ -0,0 +1,64 @@ +. +*/ + +namespace Doctrine\ORM\Tools\Console\Command\SchemaTool; + +use Symfony\Components\Console\Input\InputArgument, + Symfony\Components\Console\Input\InputOption, + Symfony\Components\Console\Input\InputInterface, + Symfony\Components\Console\Output\OutputInterface, + Symfony\Components\Console\Command\Command, + Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper, + Doctrine\ORM\Tools\SchemaTool, + Doctrine\ORM\Mapping\Driver\AbstractFileDriver; + +abstract class AbstractCommand extends Command +{ + /** + * @param InputInterface $input + * @param OutputInterface $output + * @param SchemaTool $schemaTool + * @param array $metadatas + */ + abstract protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas); + + /** + * @see Console\Command\Command + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $emHelper = $this->getHelper('em'); + + /* @var $em \Doctrine\ORM\EntityManager */ + $em = $emHelper->getEntityManager(); + + $metadatas = $em->getMetadataFactory()->getAllMetadata(); + + if ( ! empty($metadatas)) { + // Create SchemaTool + $tool = new \Doctrine\ORM\Tools\SchemaTool($em); + + $this->executeSchemaCommand($input, $output, $tool, $metadatas); + } else { + $output->write('No Metadata Classes to process.' . PHP_EOL); + } + } +} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/CreateCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/CreateCommand.php index fd724c2df..06332a3eb 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/CreateCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/CreateCommand.php @@ -23,7 +23,9 @@ namespace Doctrine\ORM\Tools\Console\Command\SchemaTool; use Symfony\Components\Console\Input\InputArgument, Symfony\Components\Console\Input\InputOption, - Symfony\Components\Console; + Symfony\Components\Console\Input\InputInterface, + Symfony\Components\Console\Output\OutputInterface, + Doctrine\ORM\Tools\SchemaTool; /** * Command to create the database schema for a set of classes based on their mappings. @@ -37,7 +39,7 @@ use Symfony\Components\Console\Input\InputArgument, * @author Jonathan Wage * @author Roman Borschel */ -class CreateCommand extends Console\Command\Command +class CreateCommand extends AbstractCommand { /** * @see Console\Command\Command @@ -50,14 +52,6 @@ class CreateCommand extends Console\Command\Command 'Processes the schema and either create it directly on EntityManager Storage Connection or generate the SQL output.' ) ->setDefinition(array( - new InputArgument( - 'from-path', InputArgument::REQUIRED, 'The path of mapping information.' - ), - new InputOption( - 'from', null, InputOption::PARAMETER_REQUIRED | InputOption::PARAMETER_IS_ARRAY, - 'Optional paths of mapping information.', - array() - ), new InputOption( 'dump-sql', null, InputOption::PARAMETER_NONE, 'Instead of try to apply generated SQLs into EntityManager Storage Connection, output them.' @@ -69,52 +63,15 @@ EOT ); } - /** - * @see Console\Command\Command - */ - protected function execute(Console\Input\InputInterface $input, Console\Output\OutputInterface $output) + protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas) { - $em = $this->getHelper('em')->getEntityManager(); - - $reader = new \Doctrine\ORM\Tools\ClassMetadataReader(); - $reader->setEntityManager($em); - - // Process source directories - $fromPaths = array_merge(array($input->getArgument('from-path')), $input->getOption('from')); - - foreach ($fromPaths as $dirName) { - $dirName = realpath($dirName); - - if ( ! file_exists($dirName)) { - throw new \InvalidArgumentException( - sprintf("Mapping directory '%s' does not exist.", $dirName) - ); - } else if ( ! is_readable($dirName)) { - throw new \InvalidArgumentException( - sprintf("Mapping directory '%s' does not have read permissions.", $dirName) - ); - } - - $reader->addMappingSource($dirName); - } - - // Retrieving ClassMetadatas - $metadatas = $reader->getMetadatas(); - - if ( ! empty($metadatas)) { - // Create SchemaTool - $tool = new \Doctrine\ORM\Tools\SchemaTool($em); - - if ($input->getOption('dump-sql') === null) { - $sqls = $tool->getCreateSchemaSql($metadatas); - $output->write(implode(';' . PHP_EOL, $sqls)); - } else { - $output->write('Creating database schema...' . PHP_EOL); - $tool->createSchema($metadatas); - $output->write('Database schema created successfully!' . PHP_EOL); - } + if ($input->getOption('dump-sql') === true) { + $sqls = $schemaTool->getCreateSchemaSql($metadatas); + $output->write(implode(';' . PHP_EOL, $sqls) . PHP_EOL); } else { - $output->write('No Metadata Classes to process.' . PHP_EOL); + $output->write('Creating database schema...' . PHP_EOL); + $schemaTool->createSchema($metadatas); + $output->write('Database schema created successfully!' . PHP_EOL); } } } \ No newline at end of file diff --git a/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/DropCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/DropCommand.php index 9bcf280e7..1c6d0c57a 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/DropCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/DropCommand.php @@ -23,7 +23,9 @@ namespace Doctrine\ORM\Tools\Console\Command\SchemaTool; use Symfony\Components\Console\Input\InputArgument, Symfony\Components\Console\Input\InputOption, - Symfony\Components\Console; + Symfony\Components\Console\Input\InputInterface, + Symfony\Components\Console\Output\OutputInterface, + Doctrine\ORM\Tools\SchemaTool; /** * Command to drop the database schema for a set of classes based on their mappings. @@ -37,7 +39,7 @@ use Symfony\Components\Console\Input\InputArgument, * @author Jonathan Wage * @author Roman Borschel */ -class DropCommand extends Console\Command\Command +class DropCommand extends AbstractCommand { /** * @see Console\Command\Command @@ -50,14 +52,6 @@ class DropCommand extends Console\Command\Command 'Processes the schema and either drop the database schema of EntityManager Storage Connection or generate the SQL output.' ) ->setDefinition(array( - new InputArgument( - 'from-path', InputArgument::REQUIRED, 'The path of mapping information.' - ), - new InputOption( - 'from', null, InputOption::PARAMETER_REQUIRED | InputOption::PARAMETER_IS_ARRAY, - 'Optional paths of mapping information.', - array() - ), new InputOption( 'dump-sql', null, InputOption::PARAMETER_NONE, 'Instead of try to apply generated SQLs into EntityManager Storage Connection, output them.' @@ -70,52 +64,15 @@ EOT ); } - /** - * @see Console\Command\Command - */ - protected function execute(Console\Input\InputInterface $input, Console\Output\OutputInterface $output) + protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas) { - $em = $this->getHelper('em')->getEntityManager(); - - $reader = new \Doctrine\ORM\Tools\ClassMetadataReader(); - $reader->setEntityManager($em); - - // Process source directories - $fromPaths = array_merge(array($input->getArgument('from-path')), $input->getOption('from')); - - foreach ($fromPaths as $dirName) { - $dirName = realpath($dirName); - - if ( ! file_exists($dirName)) { - throw new \InvalidArgumentException( - sprintf("Mapping directory '%s' does not exist.", $dirName) - ); - } else if ( ! is_readable($dirName)) { - throw new \InvalidArgumentException( - sprintf("Mapping directory '%s' does not have read permissions.", $dirName) - ); - } - - $reader->addMappingSource($dirName); - } - - // Retrieving ClassMetadatas - $metadatas = $reader->getMetadatas(); - - if ( ! empty($metadatas)) { - // Create SchemaTool - $tool = new \Doctrine\ORM\Tools\SchemaTool($em); - - if ($input->getOption('dump-sql') === null) { - $sqls = $tool->getDropSchemaSql($metadatas); - $output->write(implode(';' . PHP_EOL, $sqls)); - } else { - $output->write('Dropping database schema...' . PHP_EOL); - $tool->dropSchema($metadatas); - $output->write('Database schema dropped successfully!' . PHP_EOL); - } + if ($input->getOption('dump-sql') === true) { + $sqls = $schemaTool->getDropSchemaSql($metadatas); + $output->write(implode(';' . PHP_EOL, $sqls) . PHP_EOL); } else { - $output->write('No Metadata Classes to process.' . PHP_EOL); + $output->write('Dropping database schema...' . PHP_EOL); + $schemaTool->dropSchema($metadatas); + $output->write('Database schema dropped successfully!' . PHP_EOL); } } } \ No newline at end of file diff --git a/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/UpdateCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/UpdateCommand.php index 7d85bb6a9..32d8fd0f7 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/UpdateCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/UpdateCommand.php @@ -23,7 +23,9 @@ namespace Doctrine\ORM\Tools\Console\Command\SchemaTool; use Symfony\Components\Console\Input\InputArgument, Symfony\Components\Console\Input\InputOption, - Symfony\Components\Console; + Symfony\Components\Console\Input\InputInterface, + Symfony\Components\Console\Output\OutputInterface, + Doctrine\ORM\Tools\SchemaTool; /** * Command to update the database schema for a set of classes based on their mappings. @@ -37,7 +39,7 @@ use Symfony\Components\Console\Input\InputArgument, * @author Jonathan Wage * @author Roman Borschel */ -class UpdateCommand extends Console\Command\Command +class UpdateCommand extends AbstractCommand { /** * @see Console\Command\Command @@ -50,14 +52,6 @@ class UpdateCommand extends Console\Command\Command 'Processes the schema and either update the database schema of EntityManager Storage Connection or generate the SQL output.' ) ->setDefinition(array( - new InputArgument( - 'from-path', InputArgument::REQUIRED, 'The path of mapping information.' - ), - new InputOption( - 'from', null, InputOption::PARAMETER_REQUIRED | InputOption::PARAMETER_IS_ARRAY, - 'Optional paths of mapping information.', - array() - ), new InputOption( 'complete', null, InputOption::PARAMETER_NONE, 'If defined, all assets of the database which are not relevant to the current metadata will be dropped.' @@ -75,55 +69,18 @@ EOT ); } - /** - * @see Console\Command\Command - */ - protected function execute(Console\Input\InputInterface $input, Console\Output\OutputInterface $output) + protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas) { - $em = $this->getHelper('em')->getEntityManager(); - - $reader = new \Doctrine\ORM\Tools\ClassMetadataReader(); - $reader->setEntityManager($em); - - // Process source directories - $fromPaths = array_merge(array($input->getArgument('from-path')), $input->getOption('from')); - - foreach ($fromPaths as $dirName) { - $dirName = realpath($dirName); - - if ( ! file_exists($dirName)) { - throw new \InvalidArgumentException( - sprintf("Mapping directory '%s' does not exist.", $dirName) - ); - } else if ( ! is_readable($dirName)) { - throw new \InvalidArgumentException( - sprintf("Mapping directory '%s' does not have read permissions.", $dirName) - ); - } - - $reader->addMappingSource($dirName); - } - // Defining if update is complete or not (--complete not defined means $saveMode = true) - $saveMode = ($input->getOption('complete') === null); + $saveMode = ($input->getOption('complete') === true); - // Retrieving ClassMetadatas - $metadatas = $reader->getMetadatas(); - - if ( ! empty($metadatas)) { - // Create SchemaTool - $tool = new \Doctrine\ORM\Tools\SchemaTool($em); - - if ($input->getOption('dump-sql') === null) { - $sqls = $tool->getUpdateSchemaSql($metadatas, $saveMode); - $output->write(implode(';' . PHP_EOL, $sqls)); - } else { - $output->write('Updating database schema...' . PHP_EOL); - $tool->updateSchema($metadatas, $saveMode); - $output->write('Database schema updated successfully!' . PHP_EOL); - } + if ($input->getOption('dump-sql') === true) { + $sqls = $schemaTool->getUpdateSchemaSql($metadatas, $saveMode); + $output->write(implode(';' . PHP_EOL, $sqls) . PHP_EOL); } else { - $output->write('No Metadata Classes to process.' . PHP_EOL); + $output->write('Updating database schema...' . PHP_EOL); + $schemaTool->updateSchema($metadatas, $saveMode); + $output->write('Database schema updated successfully!' . PHP_EOL); } } } \ No newline at end of file diff --git a/lib/Doctrine/ORM/Tools/Console/MetadataFilter.php b/lib/Doctrine/ORM/Tools/Console/MetadataFilter.php new file mode 100644 index 000000000..efd720802 --- /dev/null +++ b/lib/Doctrine/ORM/Tools/Console/MetadataFilter.php @@ -0,0 +1,80 @@ +. +*/ + +namespace Doctrine\ORM\Tools\Console; + +/** + * Used by CLI Tools to restrict entity-based commands to given patterns. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 1.0 + * @version $Revision$ + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class MetadataFilter extends \FilterIterator implements \Countable +{ + /** + * Filter Metadatas by one or more filter options. + * + * @param array $metadatas + * @param array|string $filter + * @return array + */ + static public function filter(array $metadatas, $filter) + { + $metadatas = new MetadataFilter(new \ArrayIterator($metadatas), $filter); + return iterator_to_array($metadatas); + } + + private $_filter = array(); + + public function __construct(\ArrayIterator $metadata, $filter) + { + $this->_filter = (array)$filter; + parent::__construct($metadata); + } + + public function accept() + { + if (count($this->_filter) == 0) { + return true; + } + + $it = $this->getInnerIterator(); + $metadata = $it->current(); + + foreach ($this->_filter AS $filter) { + if (strpos($metadata->name, $filter) !== false) { + return true; + } + } + return false; + } + + public function count() + { + return count($this->getInnerIterator()); + } +} \ No newline at end of file diff --git a/tests/Doctrine/Tests/Mocks/EntityManagerMock.php b/tests/Doctrine/Tests/Mocks/EntityManagerMock.php index dd4a36ca4..4006ebda7 100644 --- a/tests/Doctrine/Tests/Mocks/EntityManagerMock.php +++ b/tests/Doctrine/Tests/Mocks/EntityManagerMock.php @@ -78,6 +78,7 @@ class EntityManagerMock extends \Doctrine\ORM\EntityManager $config = new \Doctrine\ORM\Configuration(); $config->setProxyDir(__DIR__ . '/../Proxies'); $config->setProxyNamespace('Doctrine\Tests\Proxies'); + $config->setMetadataDriverImpl(\Doctrine\ORM\Mapping\Driver\AnnotationDriver::create()); } if (is_null($eventManager)) { $eventManager = new \Doctrine\Common\EventManager(); diff --git a/tests/Doctrine/Tests/ORM/Functional/QueryCacheTest.php b/tests/Doctrine/Tests/ORM/Functional/QueryCacheTest.php index 46681ac05..34d317d2b 100644 --- a/tests/Doctrine/Tests/ORM/Functional/QueryCacheTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/QueryCacheTest.php @@ -83,7 +83,7 @@ class QueryCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase public function testQueryCache_NoHitSaveParserResult() { - $this->_em->getConfiguration()->setQueryCacheImpl(null); + $this->_em->getConfiguration()->setQueryCacheImpl(new ArrayCache()); $query = $this->_em->createQuery('select ux from Doctrine\Tests\Models\CMS\CmsUser ux'); @@ -103,7 +103,7 @@ class QueryCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase public function testQueryCache_HitDoesNotSaveParserResult() { - $this->_em->getConfiguration()->setQueryCacheImpl(null); + $this->_em->getConfiguration()->setQueryCacheImpl(new ArrayCache()); $query = $this->_em->createQuery('select ux from Doctrine\Tests\Models\CMS\CmsUser ux'); diff --git a/tests/Doctrine/Tests/ORM/Functional/ResultCacheTest.php b/tests/Doctrine/Tests/ORM/Functional/ResultCacheTest.php index 05bd8333d..3c5f00982 100644 --- a/tests/Doctrine/Tests/ORM/Functional/ResultCacheTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/ResultCacheTest.php @@ -82,7 +82,7 @@ class ResultCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->assertTrue($cache->contains('testing_result_cache_id')); - $this->_em->getConfiguration()->setResultCacheImpl(null); + $this->_em->getConfiguration()->setResultCacheImpl(new ArrayCache()); } public function testNativeQueryResultCaching() diff --git a/tests/Doctrine/Tests/OrmFunctionalTestCase.php b/tests/Doctrine/Tests/OrmFunctionalTestCase.php index 9e02cb285..6466b15dc 100644 --- a/tests/Doctrine/Tests/OrmFunctionalTestCase.php +++ b/tests/Doctrine/Tests/OrmFunctionalTestCase.php @@ -221,7 +221,7 @@ abstract class OrmFunctionalTestCase extends OrmTestCase } if (is_null(self::$_queryCacheImpl)) { - self::$_queryCacheImpl = new \Doctrine\Common\Cache\ArrayCache; + self::$_queryCacheImpl = new \Doctrine\Common\Cache\ArrayCache; } $this->_sqlLoggerStack = new \Doctrine\DBAL\Logging\DebugStack(); @@ -234,6 +234,8 @@ abstract class OrmFunctionalTestCase extends OrmTestCase $config->setQueryCacheImpl(self::$_queryCacheImpl); $config->setProxyDir(__DIR__ . '/Proxies'); $config->setProxyNamespace('Doctrine\Tests\Proxies'); + + $config->setMetadataDriverImpl($config->newDefaultAnnotationDriver()); $conn = $this->sharedFixture['conn']; $conn->getConfiguration()->setSQLLogger($this->_sqlLoggerStack); diff --git a/tests/Doctrine/Tests/OrmTestCase.php b/tests/Doctrine/Tests/OrmTestCase.php index 5ddf146dc..3991d5b6d 100644 --- a/tests/Doctrine/Tests/OrmTestCase.php +++ b/tests/Doctrine/Tests/OrmTestCase.php @@ -30,6 +30,9 @@ abstract class OrmTestCase extends DoctrineTestCase } else { $config->setMetadataCacheImpl(new \Doctrine\Common\Cache\ArrayCache); } + + $config->setMetadataDriverImpl($config->newDefaultAnnotationDriver()); + $config->setQueryCacheImpl(self::getSharedQueryCacheImpl()); $config->setProxyDir(__DIR__ . '/Proxies'); $config->setProxyNamespace('Doctrine\Tests\Proxies'); diff --git a/tools/sandbox/cli-config.php b/tools/sandbox/cli-config.php index dc2c9875e..5c69499b0 100644 --- a/tools/sandbox/cli-config.php +++ b/tools/sandbox/cli-config.php @@ -10,6 +10,9 @@ $classLoader->register(); $config = new \Doctrine\ORM\Configuration(); $config->setMetadataCacheImpl(new \Doctrine\Common\Cache\ArrayCache); +$driverImpl = $config->newDefaultAnnotationDriver(array(__DIR__."/Entities")); +$config->setMetadataDriverImpl($driverImpl); + $config->setProxyDir(__DIR__ . '/Proxies'); $config->setProxyNamespace('Proxies'); diff --git a/tools/sandbox/index.php b/tools/sandbox/index.php index ab1f78dd4..37879eef4 100644 --- a/tools/sandbox/index.php +++ b/tools/sandbox/index.php @@ -30,11 +30,14 @@ $proxiesClassLoader->register(); $config = new Configuration; $cache = new ApcCache; $config->setMetadataCacheImpl($cache); +$driverImpl = $config->newDefaultAnnotationDriver(array(__DIR__."/Entities")); +$config->setMetadataDriverImpl($driverImpl); $config->setQueryCacheImpl($cache); // Proxy configuration $config->setProxyDir(__DIR__ . '/Proxies'); $config->setProxyNamespace('Proxies'); +$config->setMetadataCacheImpl(new \Doctrine\Common\Cache\ArrayCache); // Database connection information $connectionOptions = array(