diff --git a/bin/developer b/bin/developer index 9dd7c792f5..b4e32d5469 100755 --- a/bin/developer +++ b/bin/developer @@ -69,6 +69,7 @@ $cli = new CLI(" . ' Phraseanet Developer Tools ', $version->getName() . ' ' . $version->getNumber()); if ($cli['configuration.store']->isSetup()) { + $cli->loadPlugins(); $helpers = [ 'db' => new ConnectionHelper($cli['orm.em']->getConnection()), 'em' => new EntityManagerHelper($cli['orm.em']) diff --git a/lib/Alchemy/Phrasea/Application.php b/lib/Alchemy/Phrasea/Application.php index 02784761c6..0bce392061 100644 --- a/lib/Alchemy/Phrasea/Application.php +++ b/lib/Alchemy/Phrasea/Application.php @@ -15,6 +15,8 @@ use Alchemy\Geonames\GeonamesServiceProvider; use Alchemy\Phrasea\Application\Helper\AclAware; use Alchemy\Phrasea\Application\Helper\ApplicationBoxAware; use Alchemy\Phrasea\Application\Helper\AuthenticatorAware; +use Alchemy\Phrasea\Cache\Factory; +use Alchemy\Phrasea\Cache\Manager; use Alchemy\Phrasea\Core\Event\Subscriber\BasketSubscriber; use Alchemy\Phrasea\Core\Event\Subscriber\BridgeSubscriber; use Alchemy\Phrasea\Core\Event\Subscriber\ExportSubscriber; @@ -78,6 +80,7 @@ use Alchemy\Phrasea\Twig\JSUniqueID; use Alchemy\Phrasea\Twig\PhraseanetExtension; use Alchemy\Phrasea\Utilities\CachedTranslator; use Dflydev\Silex\Provider\DoctrineOrm\DoctrineOrmServiceProvider; +use Doctrine\ORM\Configuration; use FFMpeg\FFMpegServiceProvider; use Gedmo\DoctrineExtensions as GedmoExtension; use MediaAlchemyst\MediaAlchemystServiceProvider; @@ -175,11 +178,11 @@ class Application extends SilexApplication $this->register(new CacheConnectionServiceProvider()); $this->register(new PhraseanetServiceProvider()); $this->register(new ConfigurationTesterServiceProvider()); - $this->register(new ORMServiceProvider()); - $this->register(new DoctrineServiceProvider(), $this['dbs.service.conf']); + $this->register(new DoctrineServiceProvider()); $this->setupDBAL(); - $this->register(new DoctrineOrmServiceProvider(), $this['orm.service.conf']); + $this->register(new DoctrineOrmServiceProvider()); $this->setupOrms(); + $this->register(new ORMServiceProvider()); $this->register(new BasketMiddlewareProvider()); $this->register(new TokenMiddlewareProvider()); $this->register(new AccountServiceProvider()); @@ -880,6 +883,30 @@ class Application extends SilexApplication private function setupOrms() { + $app = $this; + + // Override "orm.cache.configurer" service provided for benefiting + // of "phraseanet.cache-service" + $app['orm.cache.configurer'] = $app->protect(function($name, Configuration $config, $options) use ($app) { + /** @var Manager $service */ + $service = $app['phraseanet.cache-service']; + $config->setMetadataCacheImpl( + $service->factory('ORM_metadata', $app['orm.cache.driver'], $app['orm.cache.options']) + ); + $config->setQueryCacheImpl( + $service->factory('ORM_query', $app['orm.cache.driver'], $app['orm.cache.options']) + ); + $config->setResultCacheImpl( + $service->factory('ORM_result', $app['orm.cache.driver'], $app['orm.cache.options']) + ); + $config->setHydrationCacheImpl( + $service->factory('ORM_hydration', $app['orm.cache.driver'], $app['orm.cache.options']) + ); + }); + $app['orm.proxies_dir'] = $app['root.path'].'/resources/proxies'; + $app['orm.auto_generate_proxies'] = $app['debug']; + $app['orm.proxies_namespace'] = 'Alchemy\Phrasea\Model\Proxies'; + $this['orm.ems'] = $this->share($this->extend('orm.ems', function ($ems, $app) { GedmoExtension::registerAnnotations(); diff --git a/lib/Alchemy/Phrasea/Core/Provider/ORMServiceProvider.php b/lib/Alchemy/Phrasea/Core/Provider/ORMServiceProvider.php index 7db619bbeb..0bad8f83a1 100644 --- a/lib/Alchemy/Phrasea/Core/Provider/ORMServiceProvider.php +++ b/lib/Alchemy/Phrasea/Core/Provider/ORMServiceProvider.php @@ -37,43 +37,6 @@ class ORMServiceProvider implements ServiceProviderInterface { public function register(Application $app) { - /** - * Provide configuration for DoctrineServiceProvider. - */ - $app['dbs.service.conf'] = $app->share(function() use ($app) { - return array( - 'dbs.options' => $app['dbs.options'] - ); - }); - - /** - * Provide configuration for DoctrineORMServiceProvider. - */ - $app['orm.service.conf'] = $app->share(function() use ($app) { - return array( - // Override "orm.cache.configurer" service provided for benefiting - // of "phraseanet.cache-service" - "orm.cache.configurer" => $app->protect(function($name, ORMConfig $config, $options) use ($app) { - $config->setMetadataCacheImpl($app['phraseanet.cache-service']->factory( - 'ORM_metadata', $app['orm.cache.driver'], $app['orm.cache.options'] - )); - $config->setQueryCacheImpl($app['phraseanet.cache-service']->factory( - 'ORM_query', $app['orm.cache.driver'], $app['orm.cache.options'] - )); - $config->setResultCacheImpl($app['phraseanet.cache-service']->factory( - 'ORM_result', $app['orm.cache.driver'], $app['orm.cache.options'] - )); - $config->setHydrationCacheImpl($app['phraseanet.cache-service']->factory( - 'ORM_hydration', $app['orm.cache.driver'], $app['orm.cache.options'] - )); - }), - "orm.proxies_dir" => $app['root.path'].'/resources/proxies', - "orm.auto_generate_proxies" => $app['debug'], - "orm.proxies_namespace" => 'Alchemy\Phrasea\Model\Proxies', - "orm.em.options" => $app['orm.ems.options'] - ); - }); - /** * Provides DSN string using database information */ @@ -321,11 +284,21 @@ SQL; return $key; }); - $app['dbal.evm.register.listeners'] = $app->protect(function($evm) use($app) { - $evm->addEventSubscriber(new TimestampableListener()); + // Listeners should be attached with their events as info. + $app['dbal.evm.listeners'] = $app->share(function () { + return new \SplObjectStorage(); }); - $app['dbal.config.register.loggers'] = $app->protect(function($config) use($app) { + $app['dbal.evm.register.listeners'] = $app->protect(function(EventManager $evm) use ($app) { + $evm->addEventSubscriber(new TimestampableListener()); + /** @var \SplObjectStorage $listeners */ + $listeners = $app['dbal.evm.listeners']; + foreach ($listeners as $listener) { + $evm->addEventListener($listeners[$listener], $listener); + } + }); + + $app['dbal.config.register.loggers'] = $app->protect(function(Configuration $config) use ($app) { if ($app->getEnvironment() === PhraseaApplication::ENV_DEV) { $config->setSQLLogger($app['orm.query.logger']); } @@ -523,21 +496,23 @@ SQL; return $options; }); - /** - * Return orm configuration for a connection given its unique id - */ + $app['orm.options.mappings'] = $app->share(function (PhraseaApplication $app) { + return array( + array( + "type" => "annotation", + "alias" => "Phraseanet", + "use_simple_annotation_reader" => false, + "namespace" => 'Alchemy\Phrasea\Model\Entities', + "path" => $app['root.path'].'/lib/Alchemy/Phrasea/Model/Entities', + ) + ); + }); + + // Return orm configuration for a connection given its unique id $app['orm.options'] = $app->protect(function($connection) use ($app) { return array( "connection" => $connection, - "mappings" => array( - array( - "type" => "annotation", - "alias" => "Phraseanet", - "use_simple_annotation_reader" => false, - "namespace" => 'Alchemy\Phrasea\Model\Entities', - "path" => $app['root.path'].'/lib/Alchemy/Phrasea/Model/Entities', - ) - ), + "mappings" => $app['orm.options.mappings'], "types" => array( 'blob' => 'Alchemy\Phrasea\Model\Types\Blob', 'enum' => 'Alchemy\Phrasea\Model\Types\Enum', diff --git a/lib/Alchemy/Phrasea/DoctrineExtension/TablePrefix.php b/lib/Alchemy/Phrasea/DoctrineExtension/TablePrefix.php new file mode 100644 index 0000000000..1bd19a45d0 --- /dev/null +++ b/lib/Alchemy/Phrasea/DoctrineExtension/TablePrefix.php @@ -0,0 +1,50 @@ +namespace = trim((string)$namespace, '\\') . '\\'; + $this->prefix = (string)$prefix; + } + + public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs) + { + /** @var ClassMetadataInfo $classMetadata */ + $classMetadata = $eventArgs->getClassMetadata(); + if (substr($classMetadata->getName(), 0, strlen($this->namespace)) != $this->namespace) { + return; + } + + if (!$classMetadata->isInheritanceTypeSingleTable() || $classMetadata->getName() === $classMetadata->rootEntityName) { + $classMetadata->setPrimaryTable(['name' => $this->prefix . $classMetadata->getTableName()]); + } + + foreach ($classMetadata->getAssociationMappings() as $fieldName => $mapping) { + if ($mapping['type'] == ClassMetadataInfo::MANY_TO_MANY && $mapping['isOwningSide']) { + $mappedTableName = $mapping['joinTable']['name']; + $classMetadata->associationMappings[$fieldName]['joinTable']['name'] = $this->prefix . $mappedTableName; + } + } + + } +}