diff --git a/src/Kdyby/Doctrine/Configuration.php b/src/Kdyby/Doctrine/Configuration.php new file mode 100644 index 00000000..33a8efdf --- /dev/null +++ b/src/Kdyby/Doctrine/Configuration.php @@ -0,0 +1,40 @@ + + */ +class Configuration extends BaseConfiguration +{ + + public function setTargetEntityMap($targetEntityMap) + { + $this->_attributes['targetEntityMap'] = $targetEntityMap; + } + + + + public function getTargetEntityClassName($className) + { + return isset($this->_attributes['targetEntityMap'], $this->_attributes['targetEntityMap'][$className]) + ? $this->_attributes['targetEntityMap'][$className] + : $className; + } + +} diff --git a/src/Kdyby/Doctrine/Connection.php b/src/Kdyby/Doctrine/Connection.php index 9ba4952a..c76350cd 100644 --- a/src/Kdyby/Doctrine/Connection.php +++ b/src/Kdyby/Doctrine/Connection.php @@ -11,7 +11,6 @@ namespace Kdyby\Doctrine; use Doctrine; -use Doctrine\DBAL\Configuration; use Doctrine\Common\EventManager; use Kdyby; use Nette; @@ -167,7 +166,7 @@ public function prepare($statement) * @param array $schemaTypes * @return Connection */ - public static function create(array $params, Configuration $config, EventManager $eventManager, array $dbalTypes = array(), array $schemaTypes = array()) + public static function create(array $params, Doctrine\DBAL\Configuration $config, EventManager $eventManager, array $dbalTypes = array(), array $schemaTypes = array()) { foreach ($dbalTypes as $name => $className) { if (DbalType::hasType($name)) { diff --git a/src/Kdyby/Doctrine/DI/ITargetEntityProvider.php b/src/Kdyby/Doctrine/DI/ITargetEntityProvider.php new file mode 100644 index 00000000..fbdb672b --- /dev/null +++ b/src/Kdyby/Doctrine/DI/ITargetEntityProvider.php @@ -0,0 +1,35 @@ + targetEntity + * - originalEntity => [ targetEntity => , ... additional mapping data ] + * + * @author Michal Gebauer + */ +interface ITargetEntityProvider +{ + + /** + * Returns associative array of Interface => Class definition + * + * @return array + */ + function getTargetEntityMappings(); + +} diff --git a/src/Kdyby/Doctrine/DI/OrmExtension.php b/src/Kdyby/Doctrine/DI/OrmExtension.php index 41e873b5..43857b8f 100644 --- a/src/Kdyby/Doctrine/DI/OrmExtension.php +++ b/src/Kdyby/Doctrine/DI/OrmExtension.php @@ -59,6 +59,7 @@ class OrmExtension extends Nette\DI\CompilerExtension 'metadata' => array(), 'filters' => array(), 'namespaceAlias' => array(), + 'targetEntityMappings' => array(), ); /** @@ -119,6 +120,10 @@ class OrmExtension extends Nette\DI\CompilerExtension */ private $proxyAutoLoaders = array(); + /** + * @var array + */ + private $targetEntityMappings = array(); public function loadConfiguration() @@ -170,6 +175,16 @@ public function loadConfiguration() $builder->addDefinition($this->prefix('jitProxyWarmer')) ->setClass('Kdyby\Doctrine\Proxy\JitProxyWarmer'); + + if ($this->targetEntityMappings) { + $listener = $builder->addDefinition($this->prefix('resolveTargetEntityListener')) + ->setClass('Kdyby\Doctrine\Tools\ResolveTargetEntityListener') + ->addTag(Kdyby\Events\DI\EventsExtension::SUBSCRIBER_TAG); + + foreach ($this->targetEntityMappings as $originalEntity => $mapping) { + $listener->addSetup('addResolveTargetEntity', array($originalEntity, $mapping['targetEntity'], $mapping)); + } + } } @@ -189,12 +204,20 @@ protected function processEntityManager($name, array $defaults) /** @var Nette\DI\ServiceDefinition $metadataDriver */ Validators::assertField($config, 'metadata', 'array'); + Validators::assertField($config, 'targetEntityMappings', 'array'); + $config['targetEntityMappings'] = $this->normalizeTargetEntityMappings($config['targetEntityMappings']); foreach ($this->compiler->getExtensions() as $extension) { if ($extension instanceof IEntityProvider) { $metadata = $extension->getEntityMappings(); Validators::assert($metadata, 'array:1..'); $config['metadata'] = array_merge($config['metadata'], $metadata); } + + if ($extension instanceof ITargetEntityProvider) { + $targetEntities = $extension->getTargetEntityMappings(); + Validators::assert($targetEntities, 'array:1..'); + $config['targetEntityMappings'] = Nette\Utils\Arrays::mergeTree($config['targetEntityMappings'], $this->normalizeTargetEntityMappings($targetEntities)); + } } foreach (self::natSortKeys($config['metadata']) as $namespace => $driver) { @@ -216,7 +239,7 @@ protected function processEntityManager($name, array $defaults) Validators::assertField($config['dql'], 'numeric', 'array'); Validators::assertField($config['dql'], 'datetime', 'array'); $configuration = $builder->addDefinition($this->prefix($name . '.ormConfiguration')) - ->setClass('Doctrine\ORM\Configuration') + ->setClass('Kdyby\Doctrine\Configuration') ->addSetup('setMetadataCacheImpl', array($this->processCache($config['metadataCache'], $name . '.metadata'))) ->addSetup('setQueryCacheImpl', array($this->processCache($config['queryCache'], $name . '.query'))) ->addSetup('setResultCacheImpl', array($this->processCache($config['resultCache'], $name . '.ormResult'))) @@ -244,6 +267,13 @@ protected function processEntityManager($name, array $defaults) $configuration->addSetup('addFilter', array($filterName, $filterClass)); } + if ($config['targetEntityMappings']) { + $configuration->addSetup('setTargetEntityMap', array(array_map(function ($mapping) { + return $mapping['targetEntity']; + }, $config['targetEntityMappings']))); + $this->targetEntityMappings = Nette\Utils\Arrays::mergeTree($this->targetEntityMappings, $config['targetEntityMappings']); + } + // entity manager $builder->addDefinition($this->prefix($name . '.entityManager')) ->setClass('Kdyby\Doctrine\EntityManager') @@ -517,6 +547,33 @@ private function loadConfig($name) } + /** + * @param array $targetEntityMappings + * @return array + */ + private function normalizeTargetEntityMappings(array $targetEntityMappings) + { + $normalized = array(); + foreach ($targetEntityMappings as $originalEntity => $targetEntity) { + $originalEntity = ltrim($originalEntity, '\\'); + Validators::assert($targetEntity, 'array|string'); + if (is_array($targetEntity)) { + Validators::assertField($targetEntity, 'targetEntity', 'string'); + $mapping = array_merge($targetEntity, array( + 'targetEntity' => ltrim($targetEntity['targetEntity'], '\\') + )); + + } else { + $mapping = array( + 'targetEntity' => ltrim($targetEntity, '\\'), + ); + } + $normalized[$originalEntity] = $mapping; + } + return $normalized; + } + + /** * @param \Nette\Configurator $configurator diff --git a/src/Kdyby/Doctrine/EntityManager.php b/src/Kdyby/Doctrine/EntityManager.php index 0ac5ae82..503ed156 100644 --- a/src/Kdyby/Doctrine/EntityManager.php +++ b/src/Kdyby/Doctrine/EntityManager.php @@ -13,7 +13,6 @@ use Doctrine; use Doctrine\Common\EventManager; use Doctrine\DBAL\DriverManager; -use Doctrine\ORM\Configuration; use Doctrine\ORM\ORMException; use Kdyby; use Kdyby\Doctrine\Tools\NonLockingUniqueInserter; @@ -129,6 +128,10 @@ public function getDao($entityName) */ public function getClassMetadata($className) { + if ($this->getConfiguration() instanceof Kdyby\Doctrine\Configuration) { + $className = $this->getConfiguration()->getTargetEntityClassName($className); + } + if (!class_exists($className)) { throw new MissingClassException("Metadata of class $className was not found, because the class is missing or cannot be autoloaded."); } @@ -149,7 +152,7 @@ public function getClassMetadata($className) * @throws \Doctrine\ORM\ORMException * @return EntityManager */ - public static function create($conn, Configuration $config, EventManager $eventManager = NULL) + public static function create($conn, Doctrine\ORM\Configuration $config, EventManager $eventManager = NULL) { if (!$config->getMetadataDriverImpl()) { throw ORMException::missingMappingDriverImpl(); diff --git a/src/Kdyby/Doctrine/Tools/ResolveTargetEntityListener.php b/src/Kdyby/Doctrine/Tools/ResolveTargetEntityListener.php new file mode 100644 index 00000000..d9c2f34c --- /dev/null +++ b/src/Kdyby/Doctrine/Tools/ResolveTargetEntityListener.php @@ -0,0 +1,34 @@ + + */ +class ResolveTargetEntityListener extends Doctrine\ORM\Tools\ResolveTargetEntityListener implements Kdyby\Events\Subscriber +{ + + /** + * Returns an array of events this subscriber wants to listen to. + * + * @return array + */ + public function getSubscribedEvents() + { + return array( Doctrine\ORM\Events::loadClassMetadata ); + } + +}