diff --git a/DependencyInjection/Compiler/RegisterMappingsPass.php b/DependencyInjection/Compiler/RegisterMappingsPass.php new file mode 100644 index 0000000000..b18bf8ca37 --- /dev/null +++ b/DependencyInjection/Compiler/RegisterMappingsPass.php @@ -0,0 +1,95 @@ + + */ +class RegisterMappingsPass implements CompilerPassInterface +{ + private $driver; + private $driverPattern; + private $namespaces; + private $enabledParameter; + private $fallbackManagerParameter; + + public function __construct($driver, $driverPattern, $namespaces, $enabledParameter, $fallbackManagerParameter) + { + $this->driver = $driver; + $this->driverPattern = $driverPattern; + $this->namespaces = $namespaces; + $this->enabledParameter = $enabledParameter; + $this->fallbackManagerParameter = $fallbackManagerParameter; + } + + /** + * Register mappings with the metadata drivers. + * + * @param ContainerBuilder $container + */ + public function process(ContainerBuilder $container) + { + if (!$container->hasParameter($this->enabledParameter)) { + return; + } + + $chainDriverDefService = $this->getChainDriverServiceName($container); + $chainDriverDef = $container->getDefinition($chainDriverDefService); + foreach ($this->namespaces as $namespace) { + $chainDriverDef->addMethodCall('addDriver', array($this->driver, $namespace)); + } + } + + protected function getChainDriverServiceName(ContainerBuilder $container) + { + foreach (array('fos_user.model_manager_name', $this->fallbackManagerParameter) as $param) { + if ($container->hasParameter($param)) { + $name = $container->getParameter($param); + if ($name) { + return sprintf($this->driverPattern, $name); + } + } + } + + throw new ParameterNotFoundException('None of the managerParameters resulted in a valid name'); + } + + public static function createOrmMappingDriver(array $mappings) + { + $arguments = array($mappings, '.orm.xml'); + $locator = new Definition('Doctrine\Common\Persistence\Mapping\Driver\SymfonyFileLocator', $arguments); + $driver = new Definition('Doctrine\ORM\Mapping\Driver\XmlDriver', array($locator)); + + return new RegisterMappingsPass($driver, 'doctrine.orm.%s_metadata_driver', $mappings, 'fos_user.backend_type_orm', 'doctrine.default_entity_manager'); + } + + public static function createMongoDBMappingDriver($mappings) + { + $arguments = array($mappings, '.mongodb.xml'); + $locator = new Definition('Doctrine\Common\Persistence\Mapping\Driver\SymfonyFileLocator', $arguments); + $driver = new Definition('Doctrine\ODM\MongoDB\Mapping\Driver\XmlDriver', array($locator)); + + return new RegisterMappingsPass($driver, 'doctrine_mongodb.odm.%s_metadata_driver', $mappings, 'fos_user.backend_type_mongodb', 'doctrine_mongodb.odm.default_document_manager'); + } + + public static function createCouchDBMappingDriver($mappings) + { + $arguments = array($mappings, '.couchdb.xml'); + $locator = new Definition('Doctrine\Common\Persistence\Mapping\Driver\SymfonyFileLocator', $arguments); + $driver = new Definition('Doctrine\ODM\CouchDB\Mapping\Driver\XmlDriver', array($locator)); + + return new RegisterMappingsPass($driver, 'doctrine_couchdb.odm.%s_metadata_driver', $mappings, 'fos_user.backend_type_couchdb', 'doctrine_couchdb.default_document_manager'); + } +} diff --git a/DependencyInjection/FOSUserExtension.php b/DependencyInjection/FOSUserExtension.php index fe4850af8a..cb089548fe 100644 --- a/DependencyInjection/FOSUserExtension.php +++ b/DependencyInjection/FOSUserExtension.php @@ -30,6 +30,7 @@ public function load(array $configs, ContainerBuilder $container) if ('custom' !== $config['db_driver']) { $loader->load(sprintf('%s.xml', $config['db_driver'])); + $container->setParameter($this->getAlias() . '.backend_type_' . $config['db_driver'], true); } foreach (array('validator', 'security', 'util', 'mailer', 'listeners') as $basename) { diff --git a/Document/Group.php b/Document/Group.php index 9ce2d80e51..cb77931585 100644 --- a/Document/Group.php +++ b/Document/Group.php @@ -13,6 +13,15 @@ use FOS\UserBundle\Model\Group as BaseGroup; +/** + * @deprecated directly extend the classes in the Model namespace + */ abstract class Group extends BaseGroup { + public function __construct($name, $roles = array()) + { + // you should extend the class in the Model namespace directly + trigger_error(E_USER_DEPRECATED); + parent::__construct($name, $roles); + } } diff --git a/Document/User.php b/Document/User.php index fac430dad8..460fe3a1da 100644 --- a/Document/User.php +++ b/Document/User.php @@ -13,6 +13,15 @@ use FOS\UserBundle\Model\User as AbstractUser; +/** + * @deprecated directly extend the classes in the Model namespace + */ abstract class User extends AbstractUser { + public function __construct() + { + // you should extend the class in the Model namespace directly + trigger_error(E_USER_DEPRECATED); + parent::__construct(); + } } diff --git a/Entity/Group.php b/Entity/Group.php index e7a7d240c4..755c138ba7 100644 --- a/Entity/Group.php +++ b/Entity/Group.php @@ -13,6 +13,15 @@ use FOS\UserBundle\Model\Group as BaseGroup; +/** + * @deprecated directly extend the classes in the Model namespace + */ class Group extends BaseGroup { + public function __construct($name, $roles = array()) + { + // you should extend the class in the Model namespace directly + trigger_error(E_USER_DEPRECATED); + parent::__construct($name, $roles); + } } diff --git a/Entity/User.php b/Entity/User.php index 493a63e2db..4dc5e43168 100644 --- a/Entity/User.php +++ b/Entity/User.php @@ -13,6 +13,15 @@ use FOS\UserBundle\Model\User as AbstractUser; +/** + * @deprecated directly extend the classes in the Model namespace + */ abstract class User extends AbstractUser { + public function __construct() + { + // you should extend the class in the Model namespace directly + trigger_error(E_USER_DEPRECATED); + parent::__construct(); + } } diff --git a/FOSUserBundle.php b/FOSUserBundle.php index 2de4fa2a12..044dc672ab 100644 --- a/FOSUserBundle.php +++ b/FOSUserBundle.php @@ -11,9 +11,13 @@ namespace FOS\UserBundle; -use FOS\UserBundle\DependencyInjection\Compiler\ValidationPass; use Symfony\Component\HttpKernel\Bundle\Bundle; use Symfony\Component\DependencyInjection\ContainerBuilder; +use FOS\UserBundle\DependencyInjection\Compiler\ValidationPass; +use FOS\UserBundle\DependencyInjection\Compiler\RegisterMappingsPass; +use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\DoctrineOrmMappingsPass; +use Doctrine\Bundle\MongoDBBundle\DependencyInjection\Compiler\DoctrineMongoDBMappingsPass; +use Doctrine\Bundle\CouchDBBundle\DependencyInjection\Compiler\DoctrineCouchDBMappingsPass; /** * @author Matthieu Bontemps @@ -25,5 +29,38 @@ public function build(ContainerBuilder $container) { parent::build($container); $container->addCompilerPass(new ValidationPass()); + + $this->addRegisterMappingsPass($container); + } + + /** + * @param ContainerBuilder $container + */ + private function addRegisterMappingsPass(ContainerBuilder $container) + { + // the base class is only available since symfony 2.3 + $symfonyVersion = class_exists('Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass\RegisterMappingsPass'); + + $mappings = array( + realpath(__DIR__ . '/Resources/config/doctrine/model') => 'FOS\UserBundle\Model', + ); + + if ($symfonyVersion && class_exists('Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\DoctrineOrmMappingsPass')) { + $container->addCompilerPass(DoctrineOrmMappingsPass::createXmlMappingDriver($mappings, array('fos_user.model_manager_name'), 'fos_user.backend_type_orm')); + } else { + $container->addCompilerPass(RegisterMappingsPass::createOrmMappingDriver($mappings)); + } + + if ($symfonyVersion && class_exists('Doctrine\Bundle\MongoDBBundle\DependencyInjection\Compiler\DoctrineMongoDBMappingsPass')) { + $container->addCompilerPass(DoctrineMongoDBMappingsPass::createXmlMappingDriver($mappings, array('fos_user.model_manager_name'), 'fos_user.backend_type_mongodb')); + } else { + $container->addCompilerPass(RegisterMappingsPass::createMongoDBMappingDriver($mappings)); + } + + if ($symfonyVersion && class_exists('Doctrine\Bundle\CouchDBBundle\DependencyInjection\Compiler\DoctrineCouchDBMappingsPass')) { + $container->addCompilerPass(DoctrineCouchDBMappingsPass::createXmlMappingDriver($mappings, array('fos_user.model_manager_name'), 'fos_user.backend_type_couchdb')); + } else { + $container->addCompilerPass(RegisterMappingsPass::createCouchDBMappingDriver($mappings)); + } } } diff --git a/Resources/config/doctrine/Group.couchdb.xml b/Resources/config/doctrine/Group.couchdb.xml index 6f24c1bedc..875cd30022 100644 --- a/Resources/config/doctrine/Group.couchdb.xml +++ b/Resources/config/doctrine/Group.couchdb.xml @@ -1,10 +1,4 @@ - - - - - - - + diff --git a/Resources/config/doctrine/Group.mongodb.xml b/Resources/config/doctrine/Group.mongodb.xml index c153853602..e5802fd563 100644 --- a/Resources/config/doctrine/Group.mongodb.xml +++ b/Resources/config/doctrine/Group.mongodb.xml @@ -4,19 +4,6 @@ xsi:schemaLocation="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping.xsd"> - - - - - - - - - - - - - + diff --git a/Resources/config/doctrine/Group.orm.xml b/Resources/config/doctrine/Group.orm.xml index 5c2499e983..261af5211b 100644 --- a/Resources/config/doctrine/Group.orm.xml +++ b/Resources/config/doctrine/Group.orm.xml @@ -4,12 +4,6 @@ xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> - - - - - - - + diff --git a/Resources/config/doctrine/User.couchdb.xml b/Resources/config/doctrine/User.couchdb.xml index 6d230ba7a8..489fd6d10a 100644 --- a/Resources/config/doctrine/User.couchdb.xml +++ b/Resources/config/doctrine/User.couchdb.xml @@ -1,23 +1,6 @@ - - - - - - - - - - - - - - - - - - + diff --git a/Resources/config/doctrine/User.mongodb.xml b/Resources/config/doctrine/User.mongodb.xml index 11933bfcdc..53dccc8022 100644 --- a/Resources/config/doctrine/User.mongodb.xml +++ b/Resources/config/doctrine/User.mongodb.xml @@ -4,47 +4,6 @@ xsi:schemaLocation="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping.xsd"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/Resources/config/doctrine/User.orm.xml b/Resources/config/doctrine/User.orm.xml index aba6f92030..67182347eb 100644 --- a/Resources/config/doctrine/User.orm.xml +++ b/Resources/config/doctrine/User.orm.xml @@ -4,40 +4,6 @@ xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/Resources/config/doctrine/model/Group.couchdb.xml b/Resources/config/doctrine/model/Group.couchdb.xml new file mode 100644 index 0000000000..539c382cb7 --- /dev/null +++ b/Resources/config/doctrine/model/Group.couchdb.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/Resources/config/doctrine/model/Group.mongodb.xml b/Resources/config/doctrine/model/Group.mongodb.xml new file mode 100644 index 0000000000..6c62df82eb --- /dev/null +++ b/Resources/config/doctrine/model/Group.mongodb.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + diff --git a/Resources/config/doctrine/model/Group.orm.xml b/Resources/config/doctrine/model/Group.orm.xml new file mode 100644 index 0000000000..e37a754e4e --- /dev/null +++ b/Resources/config/doctrine/model/Group.orm.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + diff --git a/Resources/config/doctrine/model/User.couchdb.xml b/Resources/config/doctrine/model/User.couchdb.xml new file mode 100644 index 0000000000..43afbca7bd --- /dev/null +++ b/Resources/config/doctrine/model/User.couchdb.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Resources/config/doctrine/model/User.mongodb.xml b/Resources/config/doctrine/model/User.mongodb.xml new file mode 100644 index 0000000000..5495df5b28 --- /dev/null +++ b/Resources/config/doctrine/model/User.mongodb.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Resources/config/doctrine/model/User.orm.xml b/Resources/config/doctrine/model/User.orm.xml new file mode 100644 index 0000000000..d029621198 --- /dev/null +++ b/Resources/config/doctrine/model/User.orm.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Resources/doc/index.md b/Resources/doc/index.md index 3bc9e21443..a4c5add41e 100644 --- a/Resources/doc/index.md +++ b/Resources/doc/index.md @@ -87,7 +87,8 @@ properties or methods you find useful. This is *your* `User` class. The bundle provides base classes which are already mapped for most fields to make it easier to create your entity. Here is how you use it: -1. Extend the base `User` class (the class to use depends of your storage) +1. Extend the base `User` class (from the ``Model`` folder if you are using + any of the doctrine variants, or ``Propel`` for propel) 2. Map the `id` field. It must be protected as it is inherited from the parent class. **Warning:** @@ -95,14 +96,14 @@ to make it easier to create your entity. Here is how you use it: > When you extend from the mapped superclass provided by the bundle, don't > redefine the mapping for the other fields as it is provided by the bundle. -In the following sections, you'll see examples of how your `User` class should -look, depending on how you're storing your users (Doctrine ORM, MongoDB ODM, -or CouchDB ODM). - Your `User` class can live inside any bundle in your application. For example, if you work at "Acme" company, then you might create a bundle called `AcmeUserBundle` and place your `User` class in it. +In the following sections, you'll see examples of how your `User` class should +look, depending on how you're storing your users (Doctrine ORM, MongoDB ODM, +or CouchDB ODM). + **Note:** > The doc uses a bundle named `AcmeUserBundle`. If you want to use the same @@ -127,7 +128,7 @@ start: namespace Acme\UserBundle\Entity; -use FOS\UserBundle\Entity\User as BaseUser; +use FOS\UserBundle\Model\User as BaseUser; use Doctrine\ORM\Mapping as ORM; /** @@ -167,7 +168,7 @@ this to start: namespace Acme\UserBundle\Document; -use FOS\UserBundle\Document\User as BaseUser; +use FOS\UserBundle\Model\User as BaseUser; use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB; /** @@ -191,17 +192,17 @@ class User extends BaseUser **c) CouchDB User class** If you're persisting your users via the Doctrine CouchDB ODM, then your `User` -class should live in the `Document` namespace of your bundle and look like +class should live in the `CouchDocument` namespace of your bundle and look like this to start: ``` php Although we have used the form login mechanism in this example, the FOSUserBundle > user provider service is compatible with many other authentication methods as well. -> Please read the Symfony2 Security component documention for more information on the +> Please read the Symfony2 Security component documentation for more information on the > other types of authentication methods. The `access_control` section is where you specify the credentials necessary for @@ -344,12 +345,12 @@ Only three configuration values are required to use the bundle: * The firewall name which you configured in Step 5. * The fully qualified class name (FQCN) of the `User` class which you created in Step 4. -**Warning:** +**Note:** -> When using one of the Doctrine implementation, you need either to use the -> `auto_mapping` option of the corresponding bundle (done by default for -> DoctrineBundle in the standard distribution) or to activate the mapping -> for FOSUserBundle otherwise the base mapping will be ignored. +> FOSUserBundle uses a compiler pass to register mappings for the base +> User and Group model classes with the object manager that you configured +> it to use. (Unless specified explicitly, this is the default manager +> of your doctrine configuration.) ### Step 6: Import FOSUserBundle routing files diff --git a/Upgrade.md b/Upgrade.md index a7f17b05ec..c17f0520f5 100644 --- a/Upgrade.md +++ b/Upgrade.md @@ -4,6 +4,17 @@ Upgrade instruction This document describes the changes needed when upgrading because of a BC break. For the full list of changes, please look at the Changelog file. +## 1.3 to 2.0 + +### User and Group class + +This bundle now (registers mappings)[http://symfony.com/doc/master/cookbook/doctrine/mapping_model_classes.html] +for the classes in the Model namespace directly, instead +of having empty extending classes. The User and Group classes in the Entity and +Document namespaces are deprecated, you should update your User and Group +classes to extend the classes found in `Model`. +The old classes will stay until 2.0 is released stable, but throw deprecated warnings. + ## 1.2 to 1.3 ### Forms