From 93a4b8278119d65f95600da8bc6744ade2538d15 Mon Sep 17 00:00:00 2001 From: George Brooks Date: Mon, 26 Oct 2015 08:00:44 -0700 Subject: [PATCH 1/7] add form type options parameter --- .../Compiler/OverrideServiceCompilerPass.php | 10 +++ DependencyInjection/Configuration.php | 6 +- Form/ProfileFormType.php | 78 +++++++++++++++++++ Form/RegistrationFormType.php | 68 ++++++++++++++++ Model/UserDiscriminator.php | 11 +-- Resources/config/services.yml | 13 +++- 6 files changed, 179 insertions(+), 7 deletions(-) create mode 100644 Form/ProfileFormType.php create mode 100644 Form/RegistrationFormType.php diff --git a/DependencyInjection/Compiler/OverrideServiceCompilerPass.php b/DependencyInjection/Compiler/OverrideServiceCompilerPass.php index 8b78156..56cf3a9 100644 --- a/DependencyInjection/Compiler/OverrideServiceCompilerPass.php +++ b/DependencyInjection/Compiler/OverrideServiceCompilerPass.php @@ -18,6 +18,16 @@ public function process(ContainerBuilder $container) $container, 'fos_user.profile.form.factory', 'pugx_multi_user.profile_form_factory'); + + $this->changeService( + $container, + 'fos_user.registration.form.type', + 'pugx_multi_user.registration.form.type'); + + $this->changeService( + $container, + 'fos_user.profile.form.type', + 'pugx_multi_user.profile.form.type'); } private function changeService($container, $serviceName, $newServiceName) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 1c7a2f3..c23f273 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -81,7 +81,11 @@ public function getConfigTreeBuilder() ->end() ->end() ->end() - + ->children() + ->arrayNode('options') + ->prototype('scalar')->defaultValue(null)->end() + ->end() + ->end() ->end() ->end() ->end(); diff --git a/Form/ProfileFormType.php b/Form/ProfileFormType.php new file mode 100644 index 0000000..8668d25 --- /dev/null +++ b/Form/ProfileFormType.php @@ -0,0 +1,78 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FOS\UserBundle\Form\Type; + +use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\OptionsResolver\OptionsResolver; +use Symfony\Component\OptionsResolver\OptionsResolverInterface; +use Symfony\Component\Security\Core\Validator\Constraints\UserPassword; + +class ProfileFormType extends AbstractType +{ + private $class; + protected $options; + + /** + * @param string $class The User class name + */ + public function __construct($class, $options = null) + { + $this->class = $class; + $this->options = $options; + } + + public function buildForm(FormBuilderInterface $builder, array $options) + { + $this->buildUserForm($builder, $options); + + $builder->add('current_password', 'password', array( + 'label' => 'form.current_password', + 'translation_domain' => 'FOSUserBundle', + 'mapped' => false, + 'constraints' => new UserPassword(), + )); + } + + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults(array( + 'data_class' => $this->class, + 'intention' => 'profile', + )); + } + + // BC for SF < 2.7 + public function setDefaultOptions(OptionsResolverInterface $resolver) + { + $this->configureOptions($resolver); + } + + public function getName() + { + return 'fos_user_profile'; + } + + /** + * Builds the embedded form representing the user. + * + * @param FormBuilderInterface $builder + * @param array $options + */ + protected function buildUserForm(FormBuilderInterface $builder, array $options) + { + $builder + ->add('username', null, array('label' => 'form.username', 'translation_domain' => 'FOSUserBundle')) + ->add('email', 'email', array('label' => 'form.email', 'translation_domain' => 'FOSUserBundle')) + ; + } +} diff --git a/Form/RegistrationFormType.php b/Form/RegistrationFormType.php new file mode 100644 index 0000000..cab7d61 --- /dev/null +++ b/Form/RegistrationFormType.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PUGX\MultiUserBundle\Form; + +use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\OptionsResolver\OptionsResolver; +use Symfony\Component\OptionsResolver\OptionsResolverInterface; + +class RegistrationFormType extends AbstractType +{ + private $class; + protected $options; + + /** + * @param string $class The User class name + */ + public function __construct($class, $options = null) + { + $this->class = $class; + $this->options = $options; + } + + public function buildForm(FormBuilderInterface $builder, array $options) + { + $builder + ->add('email', 'email', array('label' => 'form.email', 'translation_domain' => 'FOSUserBundle')) + ->add('username', null, array('label' => 'form.username', 'translation_domain' => 'FOSUserBundle')) + ->add('plainPassword', 'repeated', array( + 'type' => 'password', + 'options' => array('translation_domain' => 'FOSUserBundle'), + 'first_options' => array('label' => 'form.password'), + 'second_options' => array('label' => 'form.password_confirmation'), + 'invalid_message' => 'fos_user.password.mismatch', + )) + ; + } + + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults(array( + 'data_class' => $this->class, + 'intention' => 'registration', + )); + } + + // BC for SF < 2.7 + public function setDefaultOptions(OptionsResolverInterface $resolver) + { + $this->configureOptions($resolver); + } + + public function getName() + { + return 'fos_user_registration'; + } + + +} diff --git a/Model/UserDiscriminator.php b/Model/UserDiscriminator.php index 3cd1b3f..d03a00b 100644 --- a/Model/UserDiscriminator.php +++ b/Model/UserDiscriminator.php @@ -71,7 +71,7 @@ public function getClasses() foreach ($this->conf as $entity => $conf) { $classes[] = $entity; } - + return $classes; } @@ -147,13 +147,13 @@ public function getFormType($name) { $class = $this->getClass(); $className = $this->conf[$class][$name]['form']['type']; + $options = $this->conf[$class]['options']; if (!class_exists($className)) { throw new \InvalidArgumentException(sprintf('UserDiscriminator, error getting form type : "%s" not found', $className)); } - $type = new $className($class); - + $type = new $className($class, $options); return $type; } @@ -185,7 +185,7 @@ public function getTemplate($name) { return $this->conf[$this->getClass()][$name]['template']; } - + /** * * @param array $entities @@ -219,7 +219,8 @@ protected function buildConfig(array $users) 'validation_groups' => $user['profile']['form']['validation_groups'], ), 'template' => $user['profile']['template'], - ) + ), + 'options' => $user['options'] ); } } diff --git a/Resources/config/services.yml b/Resources/config/services.yml index fb5ec4f..89bc7c3 100644 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -47,4 +47,15 @@ services: # alias pugx_user_discriminator: alias: pugx_user.manager.user_discriminator - + + pugx_multi_user.registration.form.type: + class: PUGX\MultiUserBundle\Form\RegistrationFormType + arguments: [%fos_user.model.user.class%] + tags: + - { name: form.type, alias: fos_user_registration } + + pugx_multi_user.profile.form.type: + class: PUGX\MultiUserBundle\Form\ProfileFormType + arguments: [%fos_user.model.user.class%] + tags: + - { name: form.type, alias: fos_user_profile } From 779447a0a95c45e4745e9f309c7d4db2b39198b3 Mon Sep 17 00:00:00 2001 From: George Brooks Date: Mon, 26 Oct 2015 09:51:20 -0700 Subject: [PATCH 2/7] update discriminator test for options parameter --- Tests/Model/UserDiscriminatorTest.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Tests/Model/UserDiscriminatorTest.php b/Tests/Model/UserDiscriminatorTest.php index 477c4f9..534e43d 100644 --- a/Tests/Model/UserDiscriminatorTest.php +++ b/Tests/Model/UserDiscriminatorTest.php @@ -43,7 +43,8 @@ public function setUp() 'validation_groups' => array('Profile', 'Default') ), 'template' => 'AcmeUserBundle:Profile:user_two.form.html.twig' - ) + ), + 'options' => [] ); $anotherUserParameters = array( @@ -66,7 +67,8 @@ public function setUp() 'validation_groups' => array('Profile', 'Default') ), 'template' => 'AcmeUserBundle:Profile:user_two.form.html.twig' - ) + ), + 'options' => [] ); $this->parameters = array('user_one' => $userParameters, 'user_two' => $anotherUserParameters); @@ -95,7 +97,8 @@ public function testBuildException() 'options' => array( 'validation_groups' => array('Profile', 'Default') ) - ) + ), + 'options' => [] ); $parameters = array('user' => $userParameters); From 2c5a0af1383b993eecd9ed222dc29cd51ef4fd0a Mon Sep 17 00:00:00 2001 From: George Brooks Date: Mon, 26 Oct 2015 14:01:22 -0700 Subject: [PATCH 3/7] update documentation --- Resources/doc/index.md | 352 ++++++++++++++++++++++++----------------- 1 file changed, 203 insertions(+), 149 deletions(-) diff --git a/Resources/doc/index.md b/Resources/doc/index.md index 75df871..5301abf 100644 --- a/Resources/doc/index.md +++ b/Resources/doc/index.md @@ -23,7 +23,8 @@ This version of the bundle requires Symfony dev-master and FOSUserBundle dev-mas 4. Configure the FOSUserBundle (PUGXMultiUserBundle params) 5. Configure parameters for UserDiscriminator 6. Create your controllers -7. Using the User Manager +7. Overriding forms +8. Using the User Manager ### 1. Download PUGXMultiUserBundle @@ -33,19 +34,19 @@ This version of the bundle requires Symfony dev-master and FOSUserBundle dev-mas Add the following lines in your composer.json: ``` -{ - "require": { - "friendsofsymfony/user-bundle": "2.0.*@dev", - "pugx/multi-user-bundle": "3.0.*@dev" + { + "require": { + "friendsofsymfony/user-bundle": "2.0.*@dev", + "pugx/multi-user-bundle": "3.0.*@dev" + } } -} ``` Now, run the composer to download the bundle: ``` bash -$ php composer.phar update pugx/multi-user-bundle + $ php composer.phar update pugx/multi-user-bundle ``` @@ -54,17 +55,17 @@ $ php composer.phar update pugx/multi-user-bundle Enable the bundles in the kernel: ``` php -container + public function registerAction() + { + return $this->container ->get('pugx_multi_user.registration_manager') ->register('Acme\UserBundle\Entity\UserOne'); + } } -} ``` RegistrationUserTwoController ``` php -container + public function registerAction() + { + return $this->container ->get('pugx_multi_user.registration_manager') ->register('Acme\UserBundle\Entity\UserTwo'); + } } -} ``` @@ -281,41 +287,89 @@ class RegistrationUserTwoController extends Controller something like this, if you are extending fosub ``` -{% extends "FOSUserBundle::layout.html.twig" %} -{% block fos_user_content %} - {% trans_default_domain 'FOSUserBundle' %} + {% extends "FOSUserBundle::layout.html.twig" %} -
+ {% block fos_user_content %} + {% trans_default_domain 'FOSUserBundle' %} + + {{ form_widget(form) }}
-{% endblock fos_user_content %} + {% endblock fos_user_content %} ``` +### 7. Overriding forms + **Note:** > For now only registration and profile form factories are wrapped; -if you need creat a custom FormType you have to inject the discriminator. +if you need to create a custom FormType you have to inject the discriminator. -### 7. Using the User Manager +**Overriding FOS\UserBundle\Form\Type\RegistrationFormType, FOS\UserBundle\Form\Type\ProfileFormType forms** + +You can override these forms as described in the FOSUserBundle documentation if you do __NOT__ use the `options:` option in the `pugx_multi_user:` section of `config.yml`. If you intend to override those forms and are using the `options:` option in the `pugx_multi_user:` section of `config.yml`, you __MUST__ instead override **PUGX\MultiUserBundle\Form\RegistrationFormType** and/or **PUGX\MultiUserBundle\Form\ProfileFormType**. + + +```php + + use PUGX\MultiUserBundle\Form\RegistrationFormType as BaseType; + + class SomeFormType extends BaseType + { + ... + } +``` + +The options you configure in `config.yml` become available with `$this->options` in your new form. For example: + +if `config.yml` contains: + +```yaml + + pugx_multi_user: + user: user_one + options: + option1: true + option2: false +``` + +Then in your form you can use `$this->options['option1']` to retrieve `true`. Here's an example from a form type's listener: + +```php + + $builder->addEventListener(FormEvents::PRE_SET_DATA, + function (FormEvent $event) { + $form = $event->getForm(); + if ($this->options['option1']) { + $form->add('field1'); + }; + if ($this->options['option2']) { + $form->add('field2'); + }; + }); +``` + +### 8. Using the User Manager Creating a new UserOne: ``` php -$discriminator = $this->container->get('pugx_user.manager.user_discriminator'); -$discriminator->setClass('Acme\UserBundle\Entity\UserOne'); -$userManager = $this->container->get('pugx_user_manager'); + $discriminator = $this->container->get('pugx_user.manager.user_discriminator'); + $discriminator->setClass('Acme\UserBundle\Entity\UserOne'); + + $userManager = $this->container->get('pugx_user_manager'); -$userOne = $userManager->createUser(); + $userOne = $userManager->createUser(); -$userOne->setUsername('admin'); -$userOne->setEmail('admin@mail.com'); -$userOne->setPlainPassword('123456'); -$userOne->setEnabled(true); + $userOne->setUsername('admin'); + $userOne->setEmail('admin@mail.com'); + $userOne->setPlainPassword('123456'); + $userOne->setEnabled(true); -$userManager->updateUser($userOne, true); + $userManager->updateUser($userOne, true); ``` From 1c4001ee553566ef791c148cbe118549d001192d Mon Sep 17 00:00:00 2001 From: George Brooks Date: Mon, 26 Oct 2015 14:08:30 -0700 Subject: [PATCH 4/7] repair array syntax error --- Tests/Model/UserDiscriminatorTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Tests/Model/UserDiscriminatorTest.php b/Tests/Model/UserDiscriminatorTest.php index 534e43d..49b6043 100644 --- a/Tests/Model/UserDiscriminatorTest.php +++ b/Tests/Model/UserDiscriminatorTest.php @@ -44,7 +44,7 @@ public function setUp() ), 'template' => 'AcmeUserBundle:Profile:user_two.form.html.twig' ), - 'options' => [] + 'options' => array() ); $anotherUserParameters = array( @@ -68,7 +68,7 @@ public function setUp() ), 'template' => 'AcmeUserBundle:Profile:user_two.form.html.twig' ), - 'options' => [] + 'options' => array() ); $this->parameters = array('user_one' => $userParameters, 'user_two' => $anotherUserParameters); @@ -98,7 +98,7 @@ public function testBuildException() 'validation_groups' => array('Profile', 'Default') ) ), - 'options' => [] + 'options' => array() ); $parameters = array('user' => $userParameters); From a653381f7b8d41df978b6bf12c8e21ac86a6136a Mon Sep 17 00:00:00 2001 From: George Brooks Date: Wed, 28 Oct 2015 08:46:54 -0700 Subject: [PATCH 5/7] add getUserOptions(), test --- Model/UserDiscriminator.php | 12 ++++++++++++ Tests/Model/UserDiscriminatorTest.php | 8 +++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/Model/UserDiscriminator.php b/Model/UserDiscriminator.php index d03a00b..94035ea 100644 --- a/Model/UserDiscriminator.php +++ b/Model/UserDiscriminator.php @@ -136,6 +136,18 @@ public function getUserFactory() { return $this->conf[$this->getClass()]['factory']; } + + /** + * + * @return array + */ + public function getUserOptions() + { + $class = $this->getClass(); + $options = $this->conf[$class]['options']; + + return $options; + } /** * diff --git a/Tests/Model/UserDiscriminatorTest.php b/Tests/Model/UserDiscriminatorTest.php index 49b6043..614efc8 100644 --- a/Tests/Model/UserDiscriminatorTest.php +++ b/Tests/Model/UserDiscriminatorTest.php @@ -68,7 +68,7 @@ public function setUp() ), 'template' => 'AcmeUserBundle:Profile:user_two.form.html.twig' ), - 'options' => array() + 'options' => array('option1' => true) ); $this->parameters = array('user_one' => $userParameters, 'user_two' => $anotherUserParameters); @@ -126,6 +126,12 @@ public function testGetClass() $this->discriminator->setClass('PUGX\MultiUserBundle\Tests\Stub\AnotherUser'); $this->assertEquals('PUGX\MultiUserBundle\Tests\Stub\AnotherUser', $this->discriminator->getClass()); } + + public function testGetUserOptions() + { + $this->discriminator->setClass('PUGX\MultiUserBundle\Tests\Stub\AnotherUser'); + $this->assertEquals(array('option1' => true), $this->discriminator->getUserOptions()); + } public function testSetClassPersist() { From 8f88da3ed56978f6437932e3ad842bfafd15ce1b Mon Sep 17 00:00:00 2001 From: George Brooks Date: Wed, 28 Oct 2015 15:19:13 -0700 Subject: [PATCH 6/7] add test of form with options --- Tests/Model/UserDiscriminatorTest.php | 139 +++++++++++++++----------- Tests/Stub/UserRegistrationForm.php | 11 +- 2 files changed, 93 insertions(+), 57 deletions(-) diff --git a/Tests/Model/UserDiscriminatorTest.php b/Tests/Model/UserDiscriminatorTest.php index 614efc8..649d266 100644 --- a/Tests/Model/UserDiscriminatorTest.php +++ b/Tests/Model/UserDiscriminatorTest.php @@ -13,16 +13,17 @@ class UserDiscriminatorTest extends \PHPUnit_Framework_TestCase { + public function setUp() { $this->session = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\Session')->disableOriginalConstructor()->getMock(); - - $this->event = $this->getMockBuilder('Symfony\Component\Security\Http\Event\InteractiveLoginEvent')->disableOriginalConstructor()->getMock(); - $this->token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken')->disableOriginalConstructor()->getMock(); - $this->user = new User(); - $this->userInvalid = $this->getMockBuilder('InvalidUser')->disableOriginalConstructor()->getMock(); + + $this->event = $this->getMockBuilder('Symfony\Component\Security\Http\Event\InteractiveLoginEvent')->disableOriginalConstructor()->getMock(); + $this->token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken')->disableOriginalConstructor()->getMock(); + $this->user = new User(); + $this->userInvalid = $this->getMockBuilder('InvalidUser')->disableOriginalConstructor()->getMock(); $this->userFactory = $this->getMockBuilder('PUGX\MultiUserBundle\Model\UserFactoryInterface')->disableOriginalConstructor()->getMock(); - + $userParameters = array( 'entity' => array( 'class' => 'PUGX\MultiUserBundle\Tests\Stub\User', @@ -44,7 +45,7 @@ public function setUp() ), 'template' => 'AcmeUserBundle:Profile:user_two.form.html.twig' ), - 'options' => array() + 'options' => array('option1' => true) ); $anotherUserParameters = array( @@ -70,17 +71,18 @@ public function setUp() ), 'options' => array('option1' => true) ); - + $this->parameters = array('user_one' => $userParameters, 'user_two' => $anotherUserParameters); - - $this->discriminator = new UserDiscriminator($this->session, $this->parameters); + + $this->discriminator = new UserDiscriminator($this->session, + $this->parameters); } - + /** * @expectedException \LogicException */ public function testBuildException() - { + { $userParameters = array( 'entity' => array( 'class' => 'FakeUser', @@ -100,127 +102,152 @@ public function testBuildException() ), 'options' => array() ); - - $parameters = array('user' => $userParameters); - $discriminator = new UserDiscriminator($this->session, $parameters); + + $parameters = array('user' => $userParameters); + $discriminator = new UserDiscriminator($this->session, $parameters); } - + /** * */ - public function testGetClasses() + public function testGetClasses() { - $this->assertEquals(array('PUGX\MultiUserBundle\Tests\Stub\User', 'PUGX\MultiUserBundle\Tests\Stub\AnotherUser'), $this->discriminator->getClasses()); + $this->assertEquals(array('PUGX\MultiUserBundle\Tests\Stub\User', 'PUGX\MultiUserBundle\Tests\Stub\AnotherUser'), + $this->discriminator->getClasses()); } - + /** * @expectedException \LogicException */ - public function testSetClassException() + public function testSetClassException() { $this->discriminator->setClass('ArbitaryClass'); } - - public function testGetClass() - { - $this->discriminator->setClass('PUGX\MultiUserBundle\Tests\Stub\AnotherUser'); - $this->assertEquals('PUGX\MultiUserBundle\Tests\Stub\AnotherUser', $this->discriminator->getClass()); + + public function testGetClass() + { + $this->discriminator->setClass('PUGX\MultiUserBundle\Tests\Stub\AnotherUser'); + $this->assertEquals('PUGX\MultiUserBundle\Tests\Stub\AnotherUser', + $this->discriminator->getClass()); } public function testGetUserOptions() { $this->discriminator->setClass('PUGX\MultiUserBundle\Tests\Stub\AnotherUser'); - $this->assertEquals(array('option1' => true), $this->discriminator->getUserOptions()); + $this->assertEquals(array('option1' => true), + $this->discriminator->getUserOptions()); } - - public function testSetClassPersist() - { - $this->session->expects($this->exactly(1))->method('set')->with(UserDiscriminator::SESSION_NAME, 'PUGX\MultiUserBundle\Tests\Stub\User'); - $this->discriminator->setClass('PUGX\MultiUserBundle\Tests\Stub\User', true); + + public function testSetClassPersist() + { + $this->session->expects($this->exactly(1))->method('set')->with(UserDiscriminator::SESSION_NAME, + 'PUGX\MultiUserBundle\Tests\Stub\User'); + $this->discriminator->setClass('PUGX\MultiUserBundle\Tests\Stub\User', + true); } - - public function testGetClassDefault() + + public function testGetClassDefault() { - $this->session->expects($this->exactly(1))->method('get')->with(UserDiscriminator::SESSION_NAME, null)->will($this->onConsecutiveCalls(null)); - $this->assertEquals('PUGX\MultiUserBundle\Tests\Stub\User', $this->discriminator->getClass()); + $this->session->expects($this->exactly(1))->method('get')->with(UserDiscriminator::SESSION_NAME, + null)->will($this->onConsecutiveCalls(null)); + $this->assertEquals('PUGX\MultiUserBundle\Tests\Stub\User', + $this->discriminator->getClass()); } - - public function testGetClassStored() + + public function testGetClassStored() { - $this->session->expects($this->exactly(1))->method('get')->with(UserDiscriminator::SESSION_NAME, null)->will($this->onConsecutiveCalls('PUGX\MultiUserBundle\Tests\Stub\AnotherUser')); - $this->assertEquals('PUGX\MultiUserBundle\Tests\Stub\AnotherUser', $this->discriminator->getClass()); + $this->session->expects($this->exactly(1))->method('get')->with(UserDiscriminator::SESSION_NAME, + null)->will($this->onConsecutiveCalls('PUGX\MultiUserBundle\Tests\Stub\AnotherUser')); + $this->assertEquals('PUGX\MultiUserBundle\Tests\Stub\AnotherUser', + $this->discriminator->getClass()); } - + public function testCreateUser() - { + { $expected = new AnotherUser(); - $this->session->expects($this->exactly(0))->method('get'); - + $this->session->expects($this->exactly(0))->method('get'); + $this->discriminator->setClass('PUGX\MultiUserBundle\Tests\Stub\AnotherUser'); $result = $this->discriminator->createUser(); $this->assertEquals($expected, $result); } - + public function testGetUserFactory() { $this->discriminator->setClass('PUGX\MultiUserBundle\Tests\Stub\AnotherUser'); $result = $this->discriminator->getUserFactory(); - $this->assertEquals('PUGX\MultiUserBundle\Tests\Stub\CustomUserFactory', $result); + $this->assertEquals('PUGX\MultiUserBundle\Tests\Stub\CustomUserFactory', + $result); } - + public function testGetFormTypeRegistration() { $this->discriminator->setClass('PUGX\MultiUserBundle\Tests\Stub\User'); $result = $this->discriminator->getFormType('registration'); - $this->assertEquals('PUGX\MultiUserBundle\Tests\Stub\UserRegistrationForm', get_class($result)); + $this->assertEquals('PUGX\MultiUserBundle\Tests\Stub\UserRegistrationForm', + get_class($result)); } - + + public function testGetFormTypeRegistrationWithOptions() + { + $form = new UserRegistrationForm('PUGX\MultiUserBundle\Tests\Stub\User'); + $reflectForm = new \ReflectionClass($form); + $reflectOptions = $reflectForm->getProperty('options'); + $reflectOptions->setAccessible(true); + + $this->discriminator->setClass('PUGX\MultiUserBundle\Tests\Stub\User'); + $result = $this->discriminator->getFormType('registration'); + $this->assertEquals(array('option1' => true), $reflectOptions->getValue($result)); + } + public function testGetFormTypeProfile() { $this->discriminator->setClass('PUGX\MultiUserBundle\Tests\Stub\User'); $result = $this->discriminator->getFormType('profile'); - $this->assertEquals('PUGX\MultiUserBundle\Tests\Stub\UserProfileForm', get_class($result)); + $this->assertEquals('PUGX\MultiUserBundle\Tests\Stub\UserProfileForm', + get_class($result)); } - + public function testGetFormNameRegistration() { $this->discriminator->setClass('PUGX\MultiUserBundle\Tests\Stub\AnotherUser'); $result = $this->discriminator->getFormName('registration'); $this->assertEquals('fos_user_my_registration_form', $result); } - + public function testGetFormNameProfile() { $this->discriminator->setClass('PUGX\MultiUserBundle\Tests\Stub\User'); $result = $this->discriminator->getFormName('profile'); $this->assertEquals('fos_user_profile_form', $result); } - + public function testGetValidationGroupsRegistration() { $this->discriminator->setClass('PUGX\MultiUserBundle\Tests\Stub\User'); $result = $this->discriminator->getFormValidationGroups('registration'); $this->assertEquals(array('Registration', 'Default'), $result); } - + public function testGetValidationGroupsRegistrationCustom() { $this->discriminator->setClass('PUGX\MultiUserBundle\Tests\Stub\AnotherUser'); $result = $this->discriminator->getFormValidationGroups('registration'); $this->assertEquals(array('MyRegistration', 'Default'), $result); } - + public function testGetValidationGroupsProfile() { $this->discriminator->setClass('PUGX\MultiUserBundle\Tests\Stub\User'); $result = $this->discriminator->getFormValidationGroups('profile'); $this->assertEquals(array('Profile', 'Default'), $result); } - + public function testGetRegistrationTemplate() { $this->discriminator->setClass('PUGX\MultiUserBundle\Tests\Stub\User'); $result = $this->discriminator->getTemplate('registration'); - $this->assertEquals('AcmeUserBundle:Registration:user_one.form.html.twig', $result); + $this->assertEquals('AcmeUserBundle:Registration:user_one.form.html.twig', + $result); } } diff --git a/Tests/Stub/UserRegistrationForm.php b/Tests/Stub/UserRegistrationForm.php index e9f8108..6601fc1 100644 --- a/Tests/Stub/UserRegistrationForm.php +++ b/Tests/Stub/UserRegistrationForm.php @@ -4,8 +4,17 @@ class UserRegistrationForm { + private $class; + private $options; + + public function __construct($class, $options = null) + { + $this->class = $class; + $this->options = $options; + } + public function getName() { return "form_name"; } -} \ No newline at end of file +} From 8b1bd0f40bdb44b7d44f3a6dabed33c04547bb51 Mon Sep 17 00:00:00 2001 From: George Brooks Date: Sat, 7 Nov 2015 08:04:17 -0800 Subject: [PATCH 7/7] restore add profile tests, psr settings --- Controller/ProfileManager.php | 19 ++- Controller/RegistrationManager.php | 45 +++--- Form/ProfileFormType.php | 6 +- Resources/doc/index.md | 97 +++++++++++- Tests/Controller/ProfileManagerTest.php | 154 +++++++++++++++++++ Tests/Controller/RegistrationManagerTest.php | 71 +++++---- Tests/Stub/UserProfileForm.php | 13 +- Tests/Stub/UserRegistrationForm.php | 8 +- 8 files changed, 329 insertions(+), 84 deletions(-) create mode 100644 Tests/Controller/ProfileManagerTest.php diff --git a/Controller/ProfileManager.php b/Controller/ProfileManager.php index c5a468e..6e4ed19 100644 --- a/Controller/ProfileManager.php +++ b/Controller/ProfileManager.php @@ -1,4 +1,5 @@ userDiscriminator->setClass($class); $this->controller->setContainer($this->container); $result = $this->controller->editAction($this->container->get('request')); if ($result instanceof RedirectResponse) { - return $this->controller->redirect($this->controller->get('request')->getRequestUri()); + return $result; } $template = $this->userDiscriminator->getTemplate('profile'); @@ -67,8 +69,11 @@ public function edit($class) } $form = $this->formFactory->createForm(); - return $this->container->get('templating')->renderResponse($template, array( - 'form' => $form->createView(), + + return $this->container->get('templating')->renderResponse($template, + array( + 'form' => $form->createView(), + 'templates' => $templates, )); } } diff --git a/Controller/RegistrationManager.php b/Controller/RegistrationManager.php index 0f98da2..97227e6 100644 --- a/Controller/RegistrationManager.php +++ b/Controller/RegistrationManager.php @@ -11,38 +11,33 @@ class RegistrationManager { /** - * - * @var \PUGX\MultiUserBundle\Model\UserDiscriminator + * @var \PUGX\MultiUserBundle\Model\UserDiscriminator */ protected $userDiscriminator; - + /** - * - * @var \Symfony\Component\DependencyInjection\ContainerInterface + * @var \Symfony\Component\DependencyInjection\ContainerInterface */ protected $container; - + /** - * - * @var \FOS\UserBundle\Controller\RegistrationController + * @var \FOS\UserBundle\Controller\RegistrationController */ protected $controller; - + /** - * * @var \PUGX\MultiUserBundle\Form\FormFactory */ protected $formFactory; - + /** - * - * @param \PUGX\MultiUserBundle\Model\UserDiscriminator $userDiscriminator + * @param \PUGX\MultiUserBundle\Model\UserDiscriminator $userDiscriminator * @param \Symfony\Component\DependencyInjection\ContainerInterface $container - * @param \FOS\UserBundle\Controller\RegistrationController $controller - * @param \PUGX\MultiUserBundle\Form\FormFactory $formFactory + * @param \FOS\UserBundle\Controller\RegistrationController $controller + * @param \PUGX\MultiUserBundle\Form\FormFactory $formFactory */ public function __construct(UserDiscriminator $userDiscriminator, - ContainerInterface $container, + ContainerInterface $container, RegistrationController $controller, FormFactory $formFactory) { @@ -51,30 +46,32 @@ public function __construct(UserDiscriminator $userDiscriminator, $this->controller = $controller; $this->formFactory = $formFactory; } - + /** - * * @param string $class + * * @return \Symfony\Component\HttpFoundation\RedirectResponse */ - public function register($class) + public function register($class, $templates = array()) { $this->userDiscriminator->setClass($class); - + $this->controller->setContainer($this->container); - $result = $this->controller->registerAction($this->container->get('request')); + $result = $this->controller->registerAction($this->container->get('request')); if ($result instanceof RedirectResponse) { return $result; } - + $template = $this->userDiscriminator->getTemplate('registration'); if (is_null($template)) { $template = 'FOSUserBundle:Registration:register.html.twig'; } - - $form = $this->formFactory->createForm(); + + $form = $this->formFactory->createForm(); + return $this->container->get('templating')->renderResponse($template, array( 'form' => $form->createView(), + 'templates' => $templates, )); } } diff --git a/Form/ProfileFormType.php b/Form/ProfileFormType.php index 8668d25..cf27202 100644 --- a/Form/ProfileFormType.php +++ b/Form/ProfileFormType.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace FOS\UserBundle\Form\Type; +namespace PUGX\MultiUserBundle\Form; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; @@ -19,7 +19,7 @@ class ProfileFormType extends AbstractType { - private $class; + protected $class; protected $options; /** @@ -47,7 +47,7 @@ public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults(array( 'data_class' => $this->class, - 'intention' => 'profile', + 'intention' => 'profile', )); } diff --git a/Resources/doc/index.md b/Resources/doc/index.md index 5301abf..8538383 100644 --- a/Resources/doc/index.md +++ b/Resources/doc/index.md @@ -1,7 +1,7 @@ PUGXMultiUserBundle Documentation ================================== -PUGXMultiUserBundle came by the need to use different types of users using only one fos_user service. +PUGXMultiUserBundle came by the need to have users with different attributes using only one fos_user service. In practice it is an hack that forces FOSUser bundle through custom UserManager, controllers, and forms handlers. It's just a lazy way to use for free most of the functionality of FOSUserBundle. @@ -201,6 +201,8 @@ In fact is the discriminator that has responsibility to get the user class depen type: Acme\UserBundle\Form\Type\ProfileUserOneFormType name: fos_user_profile_form validation_groups: [Profile, Default] + # profile template is optional + template: AcmeUserBundle:Profile:user_one.form.html.twig # options- is optional for passing array of options to templates options: user_two: @@ -213,6 +215,7 @@ In fact is the discriminator that has responsibility to get the user class depen profile: form: type: Acme\UserBundle\Form\Type\ProfileUserTwoFormType + template: AcmeUserBundle:Profile:user_one.form.html.twig ``` @@ -237,6 +240,19 @@ user_two_registration: #### Controllers +Sometimes your business logic requires that you render more than one template when you register a user. You can create an array of the necessary templates in the controller. The array of templates is passed with the variable `$templates`. It can then be rendered in your registration template (e.g., `AcmeUserBundle:Registration:user_one.form.html.twig` using the following snippet: + +```twig + + {% for template in templates %} + {% include template %} + {% endfor %} +``` + +Just be sure to render all the necessary `fos_user` user fields in the resulting templates. + +If you do not require multiple templates, the `$templates` variable should be omitted in the controller. + RegistrationUserOneController ``` php @@ -248,14 +264,21 @@ RegistrationUserOneController use Symfony\Bundle\FrameworkBundle\Controller\Controller; class RegistrationUserOneController extends Controller - { - public function registerAction() { - return $this->container - ->get('pugx_multi_user.registration_manager') - ->register('Acme\UserBundle\Entity\UserOne'); + public function registerAction() + { + if (condition1) { + $templates[] = 'AcmeUserBundle:Registration:first.form.html.twig'; + } + if (condition2) { + $templates[] = 'AcmeUserBundle:Registration:second.form.html.twig'; + } + + return $this->container + ->get('pugx_multi_user.registration_manager') + ->register('Acme\UserBundle\Entity\UserOne', $templates); + } } - } ``` RegistrationUserTwoController @@ -279,6 +302,64 @@ RegistrationUserTwoController } ``` +ProfileController + +The ProfileController also allows the addition of templates as in the RegistrationController. If additional templates are not required it is not necessary to extend the ProfileController. + +``` php + + getUser(); + $class = get_class($user); + switch ($class) { + case 'Acme\UserBundle\Entity\UserOne': + return $this->userOneProfileAction(); + break; + case 'Acme\UserBundle\Entity\UserTwo': + return $this->userTwoProfileAction(); + break; + default: + break; + } + + private function userOneProfileAction() + { + //create optional template array here + //omit $templates parameter below if not used + return $this->container + ->get('pugx_multi_user.profile_manager') + ->edit('Acme\UserBundle\Entity\UserOne', $templates); + } + + private function userTwoProfileAction() + { + //create optional template array here + //omit $templates parameter below if not used + return $this->container + ->get('pugx_multi_user.profile_manager') + ->edit('Acme\UserBundle\Entity\UserTwo', $templates); + } + } +``` + **Note:** @@ -318,7 +399,7 @@ You can override these forms as described in the FOSUserBundle documentation if use PUGX\MultiUserBundle\Form\RegistrationFormType as BaseType; - class SomeFormType extends BaseType + class NewRegistrationFormType extends BaseType { ... } diff --git a/Tests/Controller/ProfileManagerTest.php b/Tests/Controller/ProfileManagerTest.php new file mode 100644 index 0000000..79b8f37 --- /dev/null +++ b/Tests/Controller/ProfileManagerTest.php @@ -0,0 +1,154 @@ +discriminator = $this->getMockBuilder('PUGX\MultiUserBundle\Model\UserDiscriminator') + ->disableOriginalConstructor()->getMock(); + + $this->container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface') + ->disableOriginalConstructor()->getMock(); + + $this->controller = $this->getMockBuilder('FOS\UserBundle\Controller\ProfileController') + ->disableOriginalConstructor()->getMock(); + + $this->formFactory = $this->getMockBuilder('PUGX\MultiUserBundle\Form\FormFactory') + ->disableOriginalConstructor()->getMock(); + + $this->request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request') + ->disableOriginalConstructor()->getMock(); + + $this->redirectResponse = $this->getMockBuilder('Symfony\Component\HttpFoundation\RedirectResponse') + ->disableOriginalConstructor()->getMock(); + + $this->form = $this->getMockBuilder('Symfony\Component\Form\Form') + ->disableOriginalConstructor()->getMock(); + + $this->twig = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Templating\EngineInterface') + ->disableOriginalConstructor()->getMock(); + + $this->formView = $this->getMockBuilder('Symfony\Component\Form\FormView') + ->disableOriginalConstructor()->getMock(); + + $this->userManager = new ProfileManager($this->discriminator, $this->container, $this->controller, $this->formFactory); + } + + public function common() + { + $this->discriminator + ->expects($this->exactly(1)) + ->method('setClass') + ->with('MyUser'); + + $this->controller + ->expects($this->exactly(1)) + ->method('setContainer') + ->with($this->container); + + $this->container + ->expects($this->at(0)) + ->method('get') + ->with('request') + ->will($this->returnValue($this->request)); + } + + public function testProfileReturnRedirectResponse() + { + $this->common(); + + $this->controller + ->expects($this->exactly(1)) + ->method('editAction') + ->with($this->request) + ->will($this->returnValue($this->redirectResponse)); + + $result = $this->userManager->edit('MyUser'); + + $this->assertSame($result, $this->redirectResponse); + } + + public function testProfileReturnDefaultTemplate() + { + $this->common(); + + $this->controller + ->expects($this->exactly(1)) + ->method('editAction') + ->with($this->request) + ->will($this->returnValue(null)); + + $this->discriminator + ->expects($this->exactly(1)) + ->method('getTemplate') + ->with('profile') + ->will($this->returnValue(null)); + + $this->formFactory + ->expects($this->exactly(1)) + ->method('createForm') + ->will($this->returnValue($this->form)); + + $this->container + ->expects($this->at(1)) + ->method('get') + ->with('templating') + ->will($this->returnValue($this->twig)); + + $this->twig + ->expects($this->exactly(1)) + ->method('renderResponse') + ->with('FOSUserBundle:Profile:edit.html.twig', array('form' => $this->formView, 'templates' => array())); + + $this->form + ->expects($this->exactly(1)) + ->method('createView') + ->will($this->returnValue($this->formView)); + + $result = $this->userManager->edit('MyUser'); + } + + public function testProfileReturnSpecificTemplate() + { + $this->common(); + + $this->controller + ->expects($this->exactly(1)) + ->method('editAction') + ->with($this->request) + ->will($this->returnValue(null)); + + $this->discriminator + ->expects($this->exactly(1)) + ->method('getTemplate') + ->with('profile') + ->will($this->returnValue('PUGXMultiUserBundle:Profile:edit.html.twig')); + + $this->formFactory + ->expects($this->exactly(1)) + ->method('createForm') + ->will($this->returnValue($this->form)); + + $this->container + ->expects($this->at(1)) + ->method('get') + ->with('templating') + ->will($this->returnValue($this->twig)); + + $this->twig + ->expects($this->exactly(1)) + ->method('renderResponse') + ->with('PUGXMultiUserBundle:Profile:edit.html.twig', array('form' => $this->formView, 'templates' => array())); + + $this->form + ->expects($this->exactly(1)) + ->method('createView') + ->will($this->returnValue($this->formView)); + + $result = $this->userManager->edit('MyUser', $templates = array()); + } +} diff --git a/Tests/Controller/RegistrationManagerTest.php b/Tests/Controller/RegistrationManagerTest.php index f6ff187..b1777a7 100644 --- a/Tests/Controller/RegistrationManagerTest.php +++ b/Tests/Controller/RegistrationManagerTest.php @@ -10,46 +10,46 @@ public function setUp() { $this->discriminator = $this->getMockBuilder('PUGX\MultiUserBundle\Model\UserDiscriminator') ->disableOriginalConstructor()->getMock(); - + $this->container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface') ->disableOriginalConstructor()->getMock(); - + $this->controller = $this->getMockBuilder('FOS\UserBundle\Controller\RegistrationController') ->disableOriginalConstructor()->getMock(); - + $this->formFactory = $this->getMockBuilder('PUGX\MultiUserBundle\Form\FormFactory') ->disableOriginalConstructor()->getMock(); - + $this->request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request') ->disableOriginalConstructor()->getMock(); - + $this->redirectResponse = $this->getMockBuilder('Symfony\Component\HttpFoundation\RedirectResponse') ->disableOriginalConstructor()->getMock(); - + $this->form = $this->getMockBuilder('Symfony\Component\Form\Form') ->disableOriginalConstructor()->getMock(); - + $this->twig = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Templating\EngineInterface') ->disableOriginalConstructor()->getMock(); - + $this->formView = $this->getMockBuilder('Symfony\Component\Form\FormView') ->disableOriginalConstructor()->getMock(); - + $this->userManager = new RegistrationManager($this->discriminator, $this->container, $this->controller, $this->formFactory); } - + public function common() { $this->discriminator ->expects($this->exactly(1)) ->method('setClass') ->with('MyUser'); - + $this->controller ->expects($this->exactly(1)) ->method('setContainer') ->with($this->container); - + $this->container ->expects($this->at(0)) ->method('get') @@ -57,99 +57,98 @@ public function common() ->will($this->returnValue($this->request)); } - public function testRegisterReturnRedirectResponse() { $this->common(); - + $this->controller ->expects($this->exactly(1)) ->method('registerAction') ->with($this->request) ->will($this->returnValue($this->redirectResponse)); - + $result = $this->userManager->register('MyUser'); - + $this->assertSame($result, $this->redirectResponse); } - + public function testRegisterReturnDefaultTemplate() { $this->common(); - + $this->controller ->expects($this->exactly(1)) ->method('registerAction') ->with($this->request) ->will($this->returnValue(null)); - + $this->discriminator ->expects($this->exactly(1)) ->method('getTemplate') ->with('registration') ->will($this->returnValue(null)); - + $this->formFactory ->expects($this->exactly(1)) ->method('createForm') ->will($this->returnValue($this->form)); - + $this->container ->expects($this->at(1)) ->method('get') ->with('templating') ->will($this->returnValue($this->twig)); - + $this->twig ->expects($this->exactly(1)) ->method('renderResponse') - ->with('FOSUserBundle:Registration:register.html.twig', array('form' => $this->formView)); - + ->with('FOSUserBundle:Registration:register.html.twig', array('form' => $this->formView, 'templates' => array())); + $this->form ->expects($this->exactly(1)) ->method('createView') ->will($this->returnValue($this->formView)); - + $result = $this->userManager->register('MyUser'); } - + public function testRegisterReturnSpecificTemplate() { $this->common(); - + $this->controller ->expects($this->exactly(1)) ->method('registerAction') ->with($this->request) ->will($this->returnValue(null)); - + $this->discriminator ->expects($this->exactly(1)) ->method('getTemplate') ->with('registration') ->will($this->returnValue('PUGXMultiUserBundle:Registration:register.html.twig')); - + $this->formFactory ->expects($this->exactly(1)) ->method('createForm') ->will($this->returnValue($this->form)); - + $this->container ->expects($this->at(1)) ->method('get') ->with('templating') ->will($this->returnValue($this->twig)); - + $this->twig ->expects($this->exactly(1)) ->method('renderResponse') - ->with('PUGXMultiUserBundle:Registration:register.html.twig', array('form' => $this->formView)); - + ->with('PUGXMultiUserBundle:Registration:register.html.twig', array('form' => $this->formView, 'templates' => array())); + $this->form ->expects($this->exactly(1)) ->method('createView') ->will($this->returnValue($this->formView)); - - $result = $this->userManager->register('MyUser'); + + $result = $this->userManager->register('MyUser', $templates = array()); } -} \ No newline at end of file +} diff --git a/Tests/Stub/UserProfileForm.php b/Tests/Stub/UserProfileForm.php index 8b17b58..5e09f60 100644 --- a/Tests/Stub/UserProfileForm.php +++ b/Tests/Stub/UserProfileForm.php @@ -4,8 +4,17 @@ class UserProfileForm { + protected $class; + protected $options; + + public function __construct($class, $options = null) + { + $this->class = $class; + $this->options = $options; + } + public function getName() { - return "form_name"; + return 'form_name'; } -} \ No newline at end of file +} diff --git a/Tests/Stub/UserRegistrationForm.php b/Tests/Stub/UserRegistrationForm.php index 6601fc1..6c22a95 100644 --- a/Tests/Stub/UserRegistrationForm.php +++ b/Tests/Stub/UserRegistrationForm.php @@ -4,17 +4,17 @@ class UserRegistrationForm { - private $class; - private $options; + protected $class; + protected $options; public function __construct($class, $options = null) { - $this->class = $class; + $this->class = $class; $this->options = $options; } public function getName() { - return "form_name"; + return 'form_name'; } }