├── src
├── Resources
│ ├── views
│ │ ├── Group
│ │ │ ├── new.html.twig
│ │ │ ├── edit.html.twig
│ │ │ ├── list.html.twig
│ │ │ └── show.html.twig
│ │ ├── Profile
│ │ │ ├── edit.html.twig
│ │ │ └── show.html.twig
│ │ ├── Resetting
│ │ │ ├── email.txt.twig
│ │ │ ├── request.html.twig
│ │ │ ├── reset.html.twig
│ │ │ ├── checkEmail.html.twig
│ │ │ └── passwordAlreadyRequested.html.twig
│ │ ├── Security
│ │ │ └── login.html.twig
│ │ ├── Registration
│ │ │ ├── email.txt.twig
│ │ │ ├── register.html.twig
│ │ │ ├── checkEmail.html.twig
│ │ │ └── confirmed.html.twig
│ │ ├── ChangePassword
│ │ │ └── changePassword.html.twig
│ │ ├── UserBundle
│ │ │ ├── Group
│ │ │ │ ├── show_content.html.twig
│ │ │ │ ├── edit.html.twig
│ │ │ │ ├── list.html.twig
│ │ │ │ ├── new.html.twig
│ │ │ │ ├── show.html.twig
│ │ │ │ ├── list_content.html.twig
│ │ │ │ ├── new_content.html.twig
│ │ │ │ └── edit_content.html.twig
│ │ │ ├── Profile
│ │ │ │ ├── edit.html.twig
│ │ │ │ ├── show.html.twig
│ │ │ │ ├── show_content.html.twig
│ │ │ │ └── edit_content.html.twig
│ │ │ ├── Resetting
│ │ │ │ ├── reset.html.twig
│ │ │ │ ├── request.html.twig
│ │ │ │ ├── checkEmail.html.twig
│ │ │ │ ├── passwordAlreadyRequested.html.twig
│ │ │ │ ├── reset_content.html.twig
│ │ │ │ ├── email.txt.twig
│ │ │ │ └── request_content.html.twig
│ │ │ ├── Registration
│ │ │ │ ├── register.html.twig
│ │ │ │ ├── checkEmail.html.twig
│ │ │ │ ├── register_content.html.twig
│ │ │ │ ├── email.txt.twig
│ │ │ │ └── confirmed.html.twig
│ │ │ ├── ChangePassword
│ │ │ │ ├── changePassword.html.twig
│ │ │ │ └── changePassword_content.html.twig
│ │ │ └── Security
│ │ │ │ └── login.html.twig
│ │ └── layout.html.twig
│ ├── skeleton
│ │ └── bundle
│ │ │ ├── routing.yml.twig
│ │ │ ├── Events.php.twig
│ │ │ ├── routing.xml.twig
│ │ │ ├── model
│ │ │ ├── user_custom.php.twig
│ │ │ ├── user_orm.php.twig
│ │ │ ├── group_custom.php.twig
│ │ │ ├── group_orm.php.twig
│ │ │ ├── user_mongodb.php.twig
│ │ │ ├── group_mongodb.php.twig
│ │ │ ├── user_couchdb.php.twig
│ │ │ └── group_couchdb.php.twig
│ │ │ ├── routing.php.twig
│ │ │ ├── Bundle.php.twig
│ │ │ ├── Configuration.php.twig
│ │ │ └── Extension.php.twig
│ └── config
│ │ └── container
│ │ ├── templating_twig.xml
│ │ ├── templating_php.xml
│ │ ├── services.xml
│ │ ├── forms.xml
│ │ └── listeners.xml
├── Exception
│ ├── MissingTemplateException.php
│ ├── NoActiveUserSystemException.php
│ └── UnexpectedTypeException.php
├── Command
│ ├── Validators.php
│ ├── DeactivateUserCommand.php
│ ├── ActivateUserCommand.php
│ ├── ChangePasswordCommand.php
│ ├── CreateUserCommand.php
│ ├── DemoteUserCommand.php
│ ├── PromoteUserCommand.php
│ └── GenerateUserSysCommand.php
├── Model
│ ├── NoopGroupManager.php
│ ├── UserDiscriminatorInterface.php
│ ├── DelegatingGroupManager.php
│ ├── UserDiscriminator.php
│ ├── DelegatingUserManager.php
│ └── UserConfig.php
├── Mailer
│ └── DelegatingMailer.php
├── Doctrine
│ ├── CouchDB
│ │ └── UserListener.php
│ ├── Orm
│ │ └── UserListener.php
│ ├── MongoDB
│ │ └── UserListener.php
│ └── AbstractUserListener.php
├── Form
│ ├── Type
│ │ ├── GroupFormType.php
│ │ ├── ResettingFormType.php
│ │ ├── RegistrationFormType.php
│ │ ├── ChangePasswordFormType.php
│ │ └── ProfileFormType.php
│ └── FormFactory.php
├── EventListener
│ ├── ProfileEditListener.php
│ ├── ChangePasswordListener.php
│ ├── RequestListener.php
│ ├── RegistrationListener.php
│ ├── ResettingListener.php
│ ├── GroupListener.php
│ ├── AuthenticationListener.php
│ ├── EmailConfirmationListener.php
│ └── EventDiscriminator.php
├── Templating
│ └── MultiUserHelper.php
├── DependencyInjection
│ ├── Compiler
│ │ ├── RemoveParentServicesPass.php
│ │ ├── OverrideServiceCompilerPass.php
│ │ ├── RegisterFosUserMappingsPass.php
│ │ └── RegisterUserPass.php
│ └── RollerworksMultiUserExtension.php
├── Twig
│ └── Extension
│ │ └── MultiUserExtension.php
├── Routing
│ └── UserDiscriminatorUrlGenerator.php
├── Controller
│ └── ResettingController.php
├── RollerworksMultiUserBundle.php
└── Generator
│ └── UserBundleGenerator.php
├── Changelog.md
├── .gush.yml
├── .travis.yml
├── LICENSE
├── docs
├── user_manager.md
├── overriding_forms.md
└── overriding_templates.md
├── scripts
└── generate-events.php
├── composer.json
└── README.md
/src/Resources/views/Group/new.html.twig:
--------------------------------------------------------------------------------
1 | {% extends rollerworks_multi_user_user().getTemplate("group.new") %}
2 |
--------------------------------------------------------------------------------
/src/Resources/views/Group/edit.html.twig:
--------------------------------------------------------------------------------
1 | {% extends rollerworks_multi_user_user().getTemplate("group.edit") %}
2 |
--------------------------------------------------------------------------------
/src/Resources/views/Group/list.html.twig:
--------------------------------------------------------------------------------
1 | {% extends rollerworks_multi_user_user().getTemplate("group.list") %}
2 |
--------------------------------------------------------------------------------
/src/Resources/views/Group/show.html.twig:
--------------------------------------------------------------------------------
1 | {% extends rollerworks_multi_user_user().getTemplate("group.show") %}
2 |
--------------------------------------------------------------------------------
/src/Resources/views/Profile/edit.html.twig:
--------------------------------------------------------------------------------
1 | {% extends rollerworks_multi_user_user().getTemplate("profile.edit") %}
2 |
--------------------------------------------------------------------------------
/src/Resources/views/Profile/show.html.twig:
--------------------------------------------------------------------------------
1 | {% extends rollerworks_multi_user_user().getTemplate("profile.show") %}
2 |
--------------------------------------------------------------------------------
/src/Resources/views/Resetting/email.txt.twig:
--------------------------------------------------------------------------------
1 | {% extends rollerworks_multi_user_user().getTemplate("resetting.email") %}
2 |
--------------------------------------------------------------------------------
/src/Resources/views/Security/login.html.twig:
--------------------------------------------------------------------------------
1 | {% extends rollerworks_multi_user_user().getTemplate("security.login") %}
2 |
--------------------------------------------------------------------------------
/src/Resources/views/Resetting/request.html.twig:
--------------------------------------------------------------------------------
1 | {% extends rollerworks_multi_user_user().getTemplate("resetting.request") %}
2 |
--------------------------------------------------------------------------------
/src/Resources/views/Resetting/reset.html.twig:
--------------------------------------------------------------------------------
1 | {% extends rollerworks_multi_user_user().getTemplate("resetting.reset") %}
2 |
--------------------------------------------------------------------------------
/src/Resources/views/Registration/email.txt.twig:
--------------------------------------------------------------------------------
1 | {% extends rollerworks_multi_user_user().getTemplate("registration.email") %}
2 |
--------------------------------------------------------------------------------
/src/Resources/views/Registration/register.html.twig:
--------------------------------------------------------------------------------
1 | {% extends rollerworks_multi_user_user().getTemplate("registration.register") %}
2 |
--------------------------------------------------------------------------------
/src/Resources/views/Resetting/checkEmail.html.twig:
--------------------------------------------------------------------------------
1 | {% extends rollerworks_multi_user_user().getTemplate("resetting.check_email") %}
2 |
--------------------------------------------------------------------------------
/src/Resources/views/Registration/checkEmail.html.twig:
--------------------------------------------------------------------------------
1 | {% extends rollerworks_multi_user_user().getTemplate("registration.check_email") %}
2 |
--------------------------------------------------------------------------------
/src/Resources/views/Registration/confirmed.html.twig:
--------------------------------------------------------------------------------
1 | {% extends rollerworks_multi_user_user().getTemplate("registration.confirmation.confirmed") %}
2 |
--------------------------------------------------------------------------------
/src/Resources/views/ChangePassword/changePassword.html.twig:
--------------------------------------------------------------------------------
1 | {% extends rollerworks_multi_user_user().getTemplate("change_password.change_password") %}
2 |
--------------------------------------------------------------------------------
/src/Resources/views/Resetting/passwordAlreadyRequested.html.twig:
--------------------------------------------------------------------------------
1 | {% extends rollerworks_multi_user_user().getTemplate("resetting.password_already_requested") %}
2 |
--------------------------------------------------------------------------------
/src/Resources/views/UserBundle/Group/show_content.html.twig:
--------------------------------------------------------------------------------
1 | {% trans_default_domain 'FOSUserBundle' %}
2 |
3 |
4 |
{{ 'group.show.name'|trans }}: {{ group.getName() }}
5 |
6 |
--------------------------------------------------------------------------------
/src/Resources/views/UserBundle/Group/edit.html.twig:
--------------------------------------------------------------------------------
1 | {% extends rollerworks_multi_user_user().getTemplate("layout") %}
2 |
3 | {% block fos_user_content %}
4 | {% include "RollerworksMultiUserBundle:UserBundle/Group:edit_content.html.twig" %}
5 | {% endblock fos_user_content %}
6 |
--------------------------------------------------------------------------------
/src/Resources/views/UserBundle/Group/list.html.twig:
--------------------------------------------------------------------------------
1 | {% extends rollerworks_multi_user_user().getTemplate("layout") %}
2 |
3 | {% block fos_user_content %}
4 | {% include "RollerworksMultiUserBundle:UserBundle/Group:list_content.html.twig" %}
5 | {% endblock fos_user_content %}
6 |
--------------------------------------------------------------------------------
/src/Resources/views/UserBundle/Group/new.html.twig:
--------------------------------------------------------------------------------
1 | {% extends rollerworks_multi_user_user().getTemplate("layout") %}
2 |
3 | {% block fos_user_content %}
4 | {% include "RollerworksMultiUserBundle:UserBundle/Group:new_content.html.twig" %}
5 | {% endblock fos_user_content %}
6 |
--------------------------------------------------------------------------------
/src/Resources/views/UserBundle/Group/show.html.twig:
--------------------------------------------------------------------------------
1 | {% extends rollerworks_multi_user_user().getTemplate("layout") %}
2 |
3 | {% block fos_user_content %}
4 | {% include "RollerworksMultiUserBundle:UserBundle/Group:show_content.html.twig" %}
5 | {% endblock fos_user_content %}
6 |
--------------------------------------------------------------------------------
/src/Resources/views/UserBundle/Profile/edit.html.twig:
--------------------------------------------------------------------------------
1 | {% extends rollerworks_multi_user_user().getTemplate("layout") %}
2 |
3 | {% block fos_user_content %}
4 | {% include "RollerworksMultiUserBundle:UserBundle/Profile:edit_content.html.twig" %}
5 | {% endblock fos_user_content %}
6 |
--------------------------------------------------------------------------------
/src/Resources/views/UserBundle/Profile/show.html.twig:
--------------------------------------------------------------------------------
1 | {% extends rollerworks_multi_user_user().getTemplate("layout") %}
2 |
3 | {% block fos_user_content %}
4 | {% include "RollerworksMultiUserBundle:UserBundle/Profile:show_content.html.twig" %}
5 | {% endblock fos_user_content %}
6 |
--------------------------------------------------------------------------------
/src/Resources/views/UserBundle/Resetting/reset.html.twig:
--------------------------------------------------------------------------------
1 | {% extends rollerworks_multi_user_user().getTemplate("layout") %}
2 |
3 | {% block fos_user_content %}
4 | {% include "RollerworksMultiUserBundle:UserBundle/Resetting:reset_content.html.twig" %}
5 | {% endblock fos_user_content %}
6 |
--------------------------------------------------------------------------------
/src/Resources/views/UserBundle/Resetting/request.html.twig:
--------------------------------------------------------------------------------
1 | {% extends rollerworks_multi_user_user().getTemplate("layout") %}
2 |
3 | {% block fos_user_content %}
4 | {% include "RollerworksMultiUserBundle:UserBundle/Resetting:request_content.html.twig" %}
5 | {% endblock fos_user_content %}
6 |
--------------------------------------------------------------------------------
/src/Resources/views/UserBundle/Profile/show_content.html.twig:
--------------------------------------------------------------------------------
1 | {% trans_default_domain 'FOSUserBundle' %}
2 |
3 |
4 |
{{ 'profile.show.username'|trans }}: {{ user.username }}
5 |
{{ 'profile.show.email'|trans }}: {{ user.email }}
6 |
7 |
--------------------------------------------------------------------------------
/src/Resources/views/UserBundle/Registration/register.html.twig:
--------------------------------------------------------------------------------
1 | {% extends rollerworks_multi_user_user().getTemplate("layout") %}
2 |
3 | {% block fos_user_content %}
4 | {% include "RollerworksMultiUserBundle:UserBundle/Registration:register_content.html.twig" %}
5 | {% endblock fos_user_content %}
6 |
--------------------------------------------------------------------------------
/src/Resources/views/UserBundle/ChangePassword/changePassword.html.twig:
--------------------------------------------------------------------------------
1 | {% extends rollerworks_multi_user_user().getTemplate("layout") %}
2 |
3 | {% block fos_user_content %}
4 | {% include "RollerworksMultiUserBundle:UserBundle/ChangePassword:changePassword_content.html.twig" %}
5 | {% endblock fos_user_content %}
6 |
--------------------------------------------------------------------------------
/src/Resources/views/UserBundle/Resetting/checkEmail.html.twig:
--------------------------------------------------------------------------------
1 | {% extends rollerworks_multi_user_user().getTemplate("layout") %}
2 |
3 | {% trans_default_domain 'FOSUserBundle' %}
4 |
5 | {% block fos_user_content %}
6 |
7 | {{ 'resetting.check_email'|trans({'%email%': email}) }}
8 |
9 | {% endblock %}
10 |
--------------------------------------------------------------------------------
/src/Resources/views/UserBundle/Resetting/passwordAlreadyRequested.html.twig:
--------------------------------------------------------------------------------
1 | {% extends rollerworks_multi_user_user().getTemplate("layout") %}
2 |
3 | {% trans_default_domain 'FOSUserBundle' %}
4 |
5 | {% block fos_user_content %}
6 | {{ 'resetting.password_already_requested'|trans }}
7 | {% endblock fos_user_content %}
8 |
--------------------------------------------------------------------------------
/src/Resources/views/UserBundle/Registration/checkEmail.html.twig:
--------------------------------------------------------------------------------
1 | {% extends rollerworks_multi_user_user().getTemplate("layout") %}
2 |
3 | {% trans_default_domain 'FOSUserBundle' %}
4 |
5 | {% block fos_user_content %}
6 | {{ 'registration.check_email'|trans({'%email%': user.email}) }}
7 | {% endblock fos_user_content %}
8 |
--------------------------------------------------------------------------------
/src/Resources/skeleton/bundle/routing.yml.twig:
--------------------------------------------------------------------------------
1 | {% for name, route in routes %}
2 |
3 | {{ extension_alias }}_{{ name }}:
4 | path: {{ route.path }}
5 | defaults: { _controller: "{{ route.controller_action }}" }
6 | {% if route.method is not empty %}
7 | methods: "{{ route.method|join('|') }}"
8 | {% endif %}
9 | {% endfor %}
10 |
--------------------------------------------------------------------------------
/src/Resources/views/UserBundle/Group/list_content.html.twig:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/src/Resources/skeleton/bundle/Events.php.twig:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 | {{ form_end(form) }}
9 |
--------------------------------------------------------------------------------
/src/Resources/views/UserBundle/Profile/edit_content.html.twig:
--------------------------------------------------------------------------------
1 | {% trans_default_domain 'FOSUserBundle' %}
2 |
3 | {{ form_start(form, {'action': path(rollerworks_multi_user_user().getRoutePrefix() ~ '_profile_edit'), 'attr': {'class': 'fos_user_profile_edit'} }) }}
4 | {{ form_widget(form) }}
5 |
6 |
7 |
8 | {{ form_end(form) }}
9 |
--------------------------------------------------------------------------------
/Changelog.md:
--------------------------------------------------------------------------------
1 | Changelog
2 | =========
3 |
4 | ### 1.0.0-BETA3 (2014-09-30)
5 |
6 | This version reflects the changes done in the FOSUserBundle done after 2.0.0-alpha1
7 |
8 | * The minimum requirement for Symfony has been bumped to 2.3 (older versions are already EOLed).
9 | * Lazy loading of UserSystems is enabled by default now.
10 | * [BC break] The templating engine configuration has been removed, as well as the related code.
11 |
--------------------------------------------------------------------------------
/src/Resources/views/UserBundle/Group/edit_content.html.twig:
--------------------------------------------------------------------------------
1 | {% trans_default_domain 'FOSUserBundle' %}
2 |
3 | {{ form_start(form, {'action': path(rollerworks_multi_user_user().getRoutePrefix() ~ '_group_edit', {'groupName': group_name} ), 'attr': {'class': 'fos_user_group_edit'} }) }}
4 | {{ form_widget(form) }}
5 |
6 |
7 |
8 | {{ form_end(form) }}
9 |
--------------------------------------------------------------------------------
/src/Resources/views/UserBundle/ChangePassword/changePassword_content.html.twig:
--------------------------------------------------------------------------------
1 | {% trans_default_domain 'FOSUserBundle' %}
2 |
3 | {{ form_start(form, {'action': path(rollerworks_multi_user_user().getRoutePrefix() ~ '_change_password'), 'attr': {'class': 'fos_user_change_password'} }) }}
4 | {{ form_widget(form) }}
5 |
6 |
7 |
8 | {{ form_end(form) }}
9 |
--------------------------------------------------------------------------------
/src/Resources/views/UserBundle/Registration/register_content.html.twig:
--------------------------------------------------------------------------------
1 | {% trans_default_domain 'FOSUserBundle' %}
2 |
3 | {{ form_start(form, {'action': path(rollerworks_multi_user_user().getRoutePrefix() ~ '_registration_register'), 'attr': {'class': 'fos_user_registration_register'} }) }}
4 | {{ form_widget(form) }}
5 |
6 |
7 |
8 | {{ form_end(form) }}
9 |
--------------------------------------------------------------------------------
/src/Resources/views/UserBundle/Resetting/reset_content.html.twig:
--------------------------------------------------------------------------------
1 | {% trans_default_domain 'FOSUserBundle' %}
2 |
3 | {{ form_start(form, {'action': path(rollerworks_multi_user_user().getRoutePrefix() ~ '_resetting_reset', {'token': token}), 'attr': {'class': 'fos_user_resetting_reset'} }) }}
4 | {{ form_widget(form) }}
5 |
6 |
7 |
8 | {{ form_end(form) }}
9 |
--------------------------------------------------------------------------------
/src/Exception/MissingTemplateException.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\Exception;
13 |
14 | class MissingTemplateException extends \RuntimeException
15 | {
16 | }
17 |
--------------------------------------------------------------------------------
/src/Exception/NoActiveUserSystemException.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\Exception;
13 |
14 | class NoActiveUserSystemException extends \RuntimeException
15 | {
16 | }
17 |
--------------------------------------------------------------------------------
/src/Resources/views/UserBundle/Resetting/email.txt.twig:
--------------------------------------------------------------------------------
1 | {% trans_default_domain 'FOSUserBundle' %}
2 | {% block subject %}
3 | {% autoescape false %}
4 | {{ 'resetting.email.subject'|trans({'%username%': user.username, '%confirmationUrl%': confirmationUrl}) }}
5 | {% endautoescape %}
6 | {% endblock %}
7 | {% block body_text %}
8 | {% autoescape false %}
9 | {{ 'resetting.email.message'|trans({'%username%': user.username, '%confirmationUrl%': confirmationUrl}) }}
10 | {% endautoescape %}
11 | {% endblock %}
12 | {% block body_html %}{% endblock %}
13 |
--------------------------------------------------------------------------------
/src/Resources/views/UserBundle/Registration/email.txt.twig:
--------------------------------------------------------------------------------
1 | {% trans_default_domain 'FOSUserBundle' %}
2 | {% block subject %}
3 | {% autoescape false %}
4 | {{ 'registration.email.subject'|trans({'%username%': user.username, '%confirmationUrl%': confirmationUrl}) }}
5 | {% endautoescape %}
6 | {% endblock %}
7 | {% block body_text %}
8 | {% autoescape false %}
9 | {{ 'registration.email.message'|trans({'%username%': user.username, '%confirmationUrl%': confirmationUrl}) }}
10 | {% endautoescape %}
11 | {% endblock %}
12 | {% block body_html %}{% endblock %}
13 |
--------------------------------------------------------------------------------
/src/Resources/views/UserBundle/Registration/confirmed.html.twig:
--------------------------------------------------------------------------------
1 | {% extends rollerworks_multi_user_user().getTemplate("layout") %}
2 |
3 | {% trans_default_domain 'FOSUserBundle' %}
4 |
5 | {% block fos_user_content %}
6 | {{ 'registration.confirmed'|trans({'%username%': user.username}) }}
7 | {% if app.session is not empty %}
8 | {% set targetUrl = app.session.get('_security.' ~ app.security.token.providerKey ~ '.target_path') %}
9 | {% if targetUrl is not empty %}{{ 'registration.back'|trans }}
{% endif %}
10 | {% endif %}
11 | {% endblock fos_user_content %}
12 |
--------------------------------------------------------------------------------
/src/Resources/config/container/templating_twig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/Exception/UnexpectedTypeException.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\Exception;
13 |
14 | class UnexpectedTypeException extends \InvalidArgumentException
15 | {
16 | public function __construct($value, $expectedType)
17 | {
18 | parent::__construct(sprintf('Expected argument of type "%s", "%s" given', $expectedType, is_object($value) ? get_class($value) : gettype($value)));
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/Resources/skeleton/bundle/routing.xml.twig:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 | {% block body %}
8 | {% for name, route in routes %}
9 |
10 |
11 | {{ route.controller_action }}
12 |
13 | {% endfor %}
14 |
15 | {% endblock body %}
16 |
17 |
--------------------------------------------------------------------------------
/src/Resources/config/container/templating_php.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/Resources/skeleton/bundle/model/user_custom.php.twig:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace {{
13 |
14 | namespace }}\Model;
15 |
16 | { % block use_statements % }
17 | use FOS\UserBundle\Model\User as BaseUser;
18 |
19 | { % endblock use_statements % }
20 |
21 | { % block class_definition % }
22 | class User extends BaseUser
23 | {
24 | % endblock class_definition %
25 | }
26 | {
27 | { % block class_body % }
28 | protected $id;
29 | { % endblock class_body % }
30 | }
31 |
--------------------------------------------------------------------------------
/src/Resources/skeleton/bundle/model/user_orm.php.twig:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace {{
13 |
14 | namespace }}\Entity;
15 |
16 | { % block use_statements % }
17 | use FOS\UserBundle\Model\User as BaseUser;
18 |
19 | { % endblock use_statements % }
20 |
21 | { % block class_definition % }
22 | class User extends BaseUser
23 | {
24 | % endblock class_definition %
25 | }
26 | {
27 | { % block class_body % }
28 | protected $id;
29 | { % endblock class_body % }
30 | }
31 |
--------------------------------------------------------------------------------
/src/Resources/skeleton/bundle/model/group_custom.php.twig:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace {{
13 |
14 | namespace }}\Model;
15 |
16 | { % block use_statements % }
17 | use FOS\UserBundle\Model\Group as BaseGroup;
18 |
19 | { % endblock use_statements % }
20 |
21 | { % block class_definition % }
22 | class Group extends BaseGroup
23 | {
24 | % endblock class_definition %
25 | }
26 | {
27 | { % block class_body % }
28 | protected $id;
29 | { % endblock class_body % }
30 | }
31 |
--------------------------------------------------------------------------------
/src/Resources/skeleton/bundle/model/group_orm.php.twig:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace {{
13 |
14 | namespace }}\Entity;
15 |
16 | { % block use_statements % }
17 | use FOS\UserBundle\Model\Group as BaseGroup;
18 |
19 | { % endblock use_statements % }
20 |
21 | { % block class_definition % }
22 | class Group extends BaseGroup
23 | {
24 | % endblock class_definition %
25 | }
26 | {
27 | { % block class_body % }
28 | protected $id;
29 | { % endblock class_body % }
30 | }
31 |
--------------------------------------------------------------------------------
/src/Resources/skeleton/bundle/model/user_mongodb.php.twig:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace {{
13 |
14 | namespace }}\Document;
15 |
16 | { % block use_statements % }
17 | use FOS\UserBundle\Model\User as BaseUser;
18 |
19 | { % endblock use_statements % }
20 |
21 | { % block class_definition % }
22 | class User extends BaseUser
23 | {
24 | % endblock class_definition %
25 | }
26 | {
27 | { % block class_body % }
28 | protected $id;
29 | { % endblock class_body % }
30 | }
31 |
--------------------------------------------------------------------------------
/src/Resources/skeleton/bundle/model/group_mongodb.php.twig:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace {{
13 |
14 | namespace }}\Document;
15 |
16 | { % block use_statements % }
17 | use FOS\UserBundle\Model\Group as BaseGroup;
18 |
19 | { % endblock use_statements % }
20 |
21 | { % block class_definition % }
22 | class Group extends BaseGroup
23 | {
24 | % endblock class_definition %
25 | }
26 | {
27 | { % block class_body % }
28 | protected $id;
29 | { % endblock class_body % }
30 | }
31 |
--------------------------------------------------------------------------------
/src/Resources/skeleton/bundle/model/user_couchdb.php.twig:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace {{
13 |
14 | namespace }}\CouchDocument;
15 |
16 | { % block use_statements % }
17 | use FOS\UserBundle\Model\User as BaseUser;
18 |
19 | { % endblock use_statements % }
20 |
21 | { % block class_definition % }
22 | class User extends BaseUser
23 | {
24 | % endblock class_definition %
25 | }
26 | {
27 | { % block class_body % }
28 | protected $id;
29 | { % endblock class_body % }
30 | }
31 |
--------------------------------------------------------------------------------
/src/Resources/skeleton/bundle/model/group_couchdb.php.twig:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace {{
13 |
14 | namespace }}\CouchDocument;
15 |
16 | { % block use_statements % }
17 | use FOS\UserBundle\Model\Group as BaseGroup;
18 |
19 | { % endblock use_statements % }
20 |
21 | { % block class_definition % }
22 | class Group extends BaseGroup
23 | {
24 | % endblock class_definition %
25 | }
26 | {
27 | { % block class_body % }
28 | protected $id;
29 | { % endblock class_body % }
30 | }
31 |
--------------------------------------------------------------------------------
/src/Resources/views/UserBundle/Resetting/request_content.html.twig:
--------------------------------------------------------------------------------
1 | {% trans_default_domain 'FOSUserBundle' %}
2 |
3 |
15 |
--------------------------------------------------------------------------------
/src/Resources/skeleton/bundle/routing.php.twig:
--------------------------------------------------------------------------------
1 | add('{{ extension_alias }}_{{ name }}', new Route('{{ route.path }}', array(
16 | '_controller' => '{{ route.controller_action }}'
17 | )
18 | {% if route.method is not empty %}
19 | , array(), array(), '', array(), array('{{ route.method|join("', '") }}')
20 | {% endif %}
21 | ));
22 | {% endfor %}
23 |
24 | {% endblock body %}
25 |
26 | {% block return %}
27 | return $collection;
28 | {% endblock return %}
29 |
--------------------------------------------------------------------------------
/.gush.yml:
--------------------------------------------------------------------------------
1 | # Gush configuration file, any comments will be lost.
2 | adapter: github
3 | issue_tracker: github
4 | meta-header: "This file is part of the RollerworksMultiUserBundle package.\n\n(c) Sebastiaan Stok \n\nThis source file is subject to the MIT license that is bundled\nwith this source code in the file LICENSE."
5 | # Note. Values are regexes, relative to the root-folder
6 | meta-exclude:
7 | - '/\.twig/'
8 | table-pr:
9 | bug_fix: ['Bug Fix?', 'no']
10 | new_feature: ['New Feature?', 'no']
11 | bc_breaks: ['BC Breaks?', 'no']
12 | deprecations: ['Deprecations?', 'no']
13 | fixed_tickets: ['Fixed Tickets', '']
14 | license: [License, MIT]
15 | repo_adapter: github
16 | repo_org: rollerworks
17 | repo_name: RollerworksMultiUserBundle
18 | issue_org: rollerworks
19 | issue_repo_name: RollerworksMultiUserBundle
20 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | env:
4 | - SYMFONY_VERSION="2.3.*"
5 | - SYMFONY_VERSION="2.7.*"
6 | - SYMFONY_VERSION="2.8.*"
7 | - SYMFONY_VERSION="3.0.*"
8 |
9 | # We only install Mongo to ensure the container compiles properly with multiple db-drivers
10 | before_script:
11 | - echo "extension=mongo.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
12 | - COMPOSER_ROOT_VERSION=dev-master
13 | - composer self-update
14 | - composer require symfony/symfony:${SYMFONY_VERSION} --no-update
15 | - composer require doctrine/mongodb-odm:"1.0.*@dev" --no-update
16 | - composer require doctrine/mongodb-odm-bundle:"3.0.*@dev" --no-update
17 | - composer install
18 |
19 | php:
20 | - 5.3
21 | - 5.4
22 | - 5.5
23 | - 5.6
24 | - 7.0
25 | - hhvm
26 |
27 | matrix:
28 | allow_failures:
29 | - php: 7.0
30 |
31 | script: phpunit --configuration phpunit.xml.dist --verbose --exclude-group ""
32 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2013-2016 Sebastiaan Stok
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is furnished
8 | to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/src/Resources/views/UserBundle/Security/login.html.twig:
--------------------------------------------------------------------------------
1 | {% extends rollerworks_multi_user_user().getTemplate("layout") %}
2 |
3 | {% trans_default_domain 'FOSUserBundle' %}
4 |
5 | {% block fos_user_content %}
6 | {% if error %}
7 | {{ error.messageKey|trans(error.messageData, 'security') }}
8 | {% endif %}
9 |
10 |
24 | {% endblock fos_user_content %}
25 |
--------------------------------------------------------------------------------
/src/Resources/views/layout.html.twig:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
17 |
18 | {% for type, messages in app.session.flashbag.all() %}
19 | {% for message in messages %}
20 |
21 | {{ message }}
22 |
23 | {% endfor %}
24 | {% endfor %}
25 |
26 |
27 | {% block fos_user_content %}
28 | {% endblock fos_user_content %}
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/Command/Validators.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\Command;
13 |
14 | use Sensio\Bundle\GeneratorBundle\Command\Validators as BaseValidators;
15 |
16 | /**
17 | * Validator functions.
18 | *
19 | * @author Sebastiaan Stok
20 | */
21 | class Validators extends BaseValidators
22 | {
23 | public static function validateFormat($format)
24 | {
25 | $format = strtolower($format);
26 |
27 | if (!in_array($format, array('php', 'xml', 'yml'), true)) {
28 | throw new \RuntimeException(sprintf('Format "%s" is not supported.', $format));
29 | }
30 |
31 | return $format;
32 | }
33 |
34 | public static function validateDbDriver($format)
35 | {
36 | $format = strtolower($format);
37 |
38 | if (!in_array($format, array('orm', 'mongodb', 'couchdb', 'custom'), true)) {
39 | throw new \RuntimeException(sprintf('Format "%s" is not supported.', $format));
40 | }
41 |
42 | return $format;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/Model/NoopGroupManager.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\Model;
13 |
14 | use FOS\UserBundle\Model\GroupInterface;
15 | use FOS\UserBundle\Model\GroupManagerInterface;
16 |
17 | /**
18 | * NoopGroupManager, does nothing.
19 | *
20 | * Use this group manager as default when no group managing is used.
21 | *
22 | * @author Sebastiaan Stok
23 | */
24 | class NoopGroupManager implements GroupManagerInterface
25 | {
26 | public function getClass()
27 | {
28 | // noop
29 | }
30 |
31 | public function createGroup($name)
32 | {
33 | // noop
34 | }
35 |
36 | public function deleteGroup(GroupInterface $group)
37 | {
38 | // noop
39 | }
40 |
41 | public function findGroupBy(array $criteria)
42 | {
43 | // noop
44 | }
45 |
46 | public function findGroupByName($name)
47 | {
48 | // noop
49 | }
50 |
51 | public function findGroups()
52 | {
53 | // noop
54 | }
55 |
56 | public function updateGroup(GroupInterface $group)
57 | {
58 | // noop
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/Mailer/DelegatingMailer.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\Mailer;
13 |
14 | use FOS\UserBundle\Mailer\MailerInterface;
15 | use FOS\UserBundle\Model\UserInterface;
16 | use Rollerworks\Bundle\MultiUserBundle\Model\UserDiscriminatorInterface;
17 | use Rollerworks\Component\SfContainerInjector\ContainerInjector;
18 |
19 | class DelegatingMailer implements MailerInterface
20 | {
21 | private $userDiscriminator;
22 | private $container;
23 |
24 | public function __construct(UserDiscriminatorInterface $userDiscriminator, ContainerInjector $container)
25 | {
26 | $this->userDiscriminator = $userDiscriminator;
27 | $this->container = $container;
28 | }
29 |
30 | public function sendConfirmationEmailMessage(UserInterface $user)
31 | {
32 | $this->container->get($this->userDiscriminator->getCurrentUserConfig()->getServicePrefix().'.mailer')->sendConfirmationEmailMessage($user);
33 | }
34 |
35 | public function sendResettingEmailMessage(UserInterface $user)
36 | {
37 | $this->container->get($this->userDiscriminator->getCurrentUserConfig()->getServicePrefix().'.mailer')->sendResettingEmailMessage($user);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/Model/UserDiscriminatorInterface.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\Model;
13 |
14 | use Rollerworks\Bundle\MultiUserBundle\Exception\NoActiveUserSystemException;
15 |
16 | /**
17 | * @author Sebastiaan Stok
18 | */
19 | interface UserDiscriminatorInterface
20 | {
21 | /**
22 | * Adds a new user to the discriminator.
23 | *
24 | * @param string $name
25 | * @param UserConfig $user
26 | */
27 | public function addUser($name, UserConfig $user);
28 |
29 | /**
30 | * Set the current user.
31 | *
32 | * @param string $name
33 | */
34 | public function setCurrentUser($name);
35 |
36 | /**
37 | * Returns the name of the current user.
38 | *
39 | * @return string|null
40 | */
41 | public function getCurrentUser();
42 |
43 | /**
44 | * Returns the configuration of the current user.
45 | *
46 | * This must throw an NoActiveUserSystemException when there is no user-system active.
47 | *
48 | * @throws NoActiveUserSystemException when there is no user-system active
49 | *
50 | * @return UserConfig
51 | */
52 | public function getCurrentUserConfig();
53 | }
54 |
--------------------------------------------------------------------------------
/src/Doctrine/CouchDB/UserListener.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\Doctrine\CouchDB;
13 |
14 | use Doctrine\ODM\CouchDB\Event;
15 | use Doctrine\ODM\CouchDB\Event\LifecycleEventArgs;
16 | use FOS\UserBundle\Model\UserInterface;
17 | use Rollerworks\Bundle\MultiUserBundle\Doctrine\AbstractUserListener;
18 |
19 | /**
20 | * @author Sebastiaan Stok
21 | * @author Christophe Coevoet
22 | */
23 | class UserListener extends AbstractUserListener
24 | {
25 | public function getSubscribedEvents()
26 | {
27 | return array(
28 | Event::prePersist,
29 | Event::preUpdate,
30 | );
31 | }
32 |
33 | /**
34 | * @param LifecycleEventArgs $args
35 | */
36 | public function prePersist($args)
37 | {
38 | $object = $args->getDocument();
39 | if ($object instanceof UserInterface) {
40 | $this->updateUserFields($object);
41 | }
42 | }
43 |
44 | /**
45 | * @param LifecycleEventArgs $args
46 | */
47 | public function preUpdate($args)
48 | {
49 | $object = $args->getDocument();
50 | if ($object instanceof UserInterface) {
51 | $this->updateUserFields($object);
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/Form/Type/GroupFormType.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\Form\Type;
13 |
14 | use Symfony\Component\Form\AbstractType;
15 | use Symfony\Component\Form\FormBuilderInterface;
16 | use Symfony\Component\OptionsResolver\OptionsResolverInterface;
17 |
18 | class GroupFormType extends AbstractType
19 | {
20 | /**
21 | * @var string
22 | */
23 | private $class;
24 |
25 | /**
26 | * @var string
27 | */
28 | private $typeName;
29 |
30 | /**
31 | * @param string $class The User class name
32 | * @param string $typeName The FormType name
33 | */
34 | public function __construct($class, $typeName)
35 | {
36 | $this->class = $class;
37 | $this->typeName = $typeName;
38 | }
39 |
40 | public function buildForm(FormBuilderInterface $builder, array $options)
41 | {
42 | $builder->add('name', null, array('label' => 'form.group_name', 'translation_domain' => 'FOSUserBundle'));
43 | }
44 |
45 | public function setDefaultOptions(OptionsResolverInterface $resolver)
46 | {
47 | $resolver->setDefaults(array(
48 | 'data_class' => $this->class,
49 | 'intention' => 'group',
50 | ));
51 | }
52 |
53 | public function getName()
54 | {
55 | return $this->typeName;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/Resources/skeleton/bundle/Bundle.php.twig:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace {{
13 |
14 | namespace }};
15 |
16 | { % block use_statements % }
17 | use Rollerworks\Bundle\MultiUserBundle\DependencyInjection\Compiler\RegisterFosUserMappingsPass;
18 | use Symfony\Component\DependencyInjection\ContainerBuilder;
19 | use Symfony\Component\HttpKernel\Bundle\Bundle;
20 |
21 | { % endblock use_statements % }
22 |
23 | { % block class_definition % }
24 | class
25 | {
26 | { bundle }
27 | } extends Bundle
28 | { % endblock class_definition % }
29 | {
30 | { % block class_body % }
31 | /**
32 | * {@inheritdoc}
33 | */
34 | public function build(ContainerBuilder $container)
35 | {
36 | parent::build($container);
37 | { % if {
38 | db_driver == 'orm' %
39 | }
40 | $container->addCompilerPass(RegisterFosUserMappingsPass::createOrmMappingDriver('{{ extension_alias }}')); }
41 | { % elseif {
42 | db_driver == 'mongodb' %
43 | }
44 | $container->addCompilerPass(RegisterFosUserMappingsPass::createMongoDBMappingDriver('{{ extension_alias }}')); }
45 | { % elseif {
46 | db_driver == 'couchdb' %
47 | }
48 | $container->addCompilerPass(RegisterFosUserMappingsPass::createCouchDBMappingDriver('{{ extension_alias }}')); }
49 | { % endif % }
50 | }
51 | { % endblock class_body % }
52 | }
53 |
--------------------------------------------------------------------------------
/src/EventListener/ProfileEditListener.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\EventListener;
13 |
14 | use FOS\UserBundle\Event\FormEvent;
15 | use FOS\UserBundle\FOSUserEvents;
16 | use Rollerworks\Bundle\MultiUserBundle\Model\UserDiscriminatorInterface;
17 | use Symfony\Component\EventDispatcher\EventSubscriberInterface;
18 | use Symfony\Component\HttpFoundation\RedirectResponse;
19 | use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
20 |
21 | class ProfileEditListener implements EventSubscriberInterface
22 | {
23 | private $router;
24 | private $userDiscriminator;
25 |
26 | public function __construct(UrlGeneratorInterface $router, UserDiscriminatorInterface $userDiscriminator)
27 | {
28 | $this->router = $router;
29 | $this->userDiscriminator = $userDiscriminator;
30 | }
31 |
32 | public static function getSubscribedEvents()
33 | {
34 | return array(
35 | FOSUserEvents::PROFILE_EDIT_SUCCESS => array('onProfileEditSuccess', 1),
36 | );
37 | }
38 |
39 | public function onProfileEditSuccess(FormEvent $event)
40 | {
41 | if (null === $event->getResponse()) {
42 | $url = $this->router->generate($this->userDiscriminator->getCurrentUserConfig()->getRoutePrefix().'_profile_show');
43 | $event->setResponse(new RedirectResponse($url));
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/Templating/MultiUserHelper.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\Templating;
13 |
14 | use Rollerworks\Bundle\MultiUserBundle\Model\UserConfig;
15 | use Rollerworks\Bundle\MultiUserBundle\Model\UserDiscriminatorInterface;
16 | use Symfony\Component\Templating\Helper\Helper;
17 |
18 | /**
19 | * @author Sebastiaan Stok
20 | */
21 | class MultiUserHelper extends Helper
22 | {
23 | private $userDiscriminator;
24 |
25 | /**
26 | * @param UserDiscriminatorInterface $userDiscriminator
27 | */
28 | public function __construct(UserDiscriminatorInterface $userDiscriminator)
29 | {
30 | $this->userDiscriminator = $userDiscriminator;
31 | }
32 |
33 | /**
34 | * @return string|null
35 | */
36 | public function getUser()
37 | {
38 | return $this->userDiscriminator->getCurrentUser();
39 | }
40 |
41 | /**
42 | * @return UserConfig
43 | */
44 | public function getUserConfig()
45 | {
46 | return $this->userDiscriminator->getCurrentUserConfig();
47 | }
48 |
49 | /**
50 | * @return string
51 | */
52 | public function __toString()
53 | {
54 | return (string) $this->getUser();
55 | }
56 |
57 | /**
58 | * {@inheritdoc}
59 | */
60 | public function getName()
61 | {
62 | return 'rollerworks_multi_user';
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/EventListener/ChangePasswordListener.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\EventListener;
13 |
14 | use FOS\UserBundle\Event\FormEvent;
15 | use FOS\UserBundle\FOSUserEvents;
16 | use Rollerworks\Bundle\MultiUserBundle\Model\UserDiscriminatorInterface;
17 | use Symfony\Component\EventDispatcher\EventSubscriberInterface;
18 | use Symfony\Component\HttpFoundation\RedirectResponse;
19 | use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
20 |
21 | class ChangePasswordListener implements EventSubscriberInterface
22 | {
23 | private $router;
24 | private $userDiscriminator;
25 |
26 | public function __construct(UrlGeneratorInterface $router, UserDiscriminatorInterface $userDiscriminator)
27 | {
28 | $this->router = $router;
29 | $this->userDiscriminator = $userDiscriminator;
30 | }
31 |
32 | public static function getSubscribedEvents()
33 | {
34 | return array(
35 | FOSUserEvents::CHANGE_PASSWORD_SUCCESS => array('onChangePasswordSuccess', 1),
36 | );
37 | }
38 |
39 | public function onChangePasswordSuccess(FormEvent $event)
40 | {
41 | if (null === $event->getResponse()) {
42 | $url = $this->router->generate($this->userDiscriminator->getCurrentUserConfig()->getRoutePrefix().'_profile_show');
43 | $event->setResponse(new RedirectResponse($url));
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/DependencyInjection/Compiler/RemoveParentServicesPass.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\DependencyInjection\Compiler;
13 |
14 | use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
15 | use Symfony\Component\DependencyInjection\ContainerBuilder;
16 |
17 | /**
18 | * RemoveParentServicesPass, marks the parent 'FOSUserBundle' services as abstract.
19 | *
20 | * By making them abstract they are removed and prevent any conflict or container bloat.
21 | *
22 | * @author Sebastiaan Stok
23 | *
24 | * @codeCoverageIgnore
25 | */
26 | class RemoveParentServicesPass implements CompilerPassInterface
27 | {
28 | public function process(ContainerBuilder $container)
29 | {
30 | $container->getDefinition('fos_user.listener.authentication')->setAbstract(true)->clearTags();
31 | $container->getDefinition('fos_user.listener.resetting')->setAbstract(true)->clearTags();
32 |
33 | // Forms
34 | $container->getDefinition('fos_user.registration.form.type')->setAbstract(true);
35 | $container->getDefinition('fos_user.resetting.form.type')->setAbstract(true);
36 | $container->getDefinition('fos_user.profile.form.type')->setAbstract(true);
37 | $container->getDefinition('fos_user.change_password.form.type')->setAbstract(true);
38 | $container->getDefinition('fos_user.group.form.type')->setAbstract(true);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/Twig/Extension/MultiUserExtension.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\Twig\Extension;
13 |
14 | use Rollerworks\Bundle\MultiUserBundle\Model\UserDiscriminatorInterface;
15 |
16 | /**
17 | * @author Sebastiaan Stok
18 | */
19 | class MultiUserExtension extends \Twig_Extension
20 | {
21 | private $userDiscriminator;
22 |
23 | /**
24 | * @param UserDiscriminatorInterface $userDiscriminator
25 | */
26 | public function __construct(UserDiscriminatorInterface $userDiscriminator)
27 | {
28 | $this->userDiscriminator = $userDiscriminator;
29 | }
30 |
31 | /**
32 | * {@inheritdoc}
33 | */
34 | public function getFunctions()
35 | {
36 | return array(
37 | new \Twig_SimpleFunction('rollerworks_multi_user_user', array($this, 'getCurrentUser')),
38 | );
39 | }
40 |
41 | /**
42 | * @param bool $getName
43 | *
44 | * @return \Rollerworks\Bundle\MultiUserBundle\Model\UserConfig|string|null
45 | */
46 | public function getCurrentUser($getName = false)
47 | {
48 | if ($getName) {
49 | return $this->userDiscriminator->getCurrentUser();
50 | }
51 |
52 | return $this->userDiscriminator->getCurrentUserConfig();
53 | }
54 |
55 | /**
56 | * {@inheritdoc}
57 | */
58 | public function getName()
59 | {
60 | return 'rollerworks_multi_user';
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/Command/DeactivateUserCommand.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\Command;
13 |
14 | use FOS\UserBundle\Command\DeactivateUserCommand as BaseDeactivateUserCommand;
15 | use Rollerworks\Bundle\MultiUserBundle\Model\UserDiscriminatorInterface;
16 | use Symfony\Component\Console\Input\InputInterface;
17 | use Symfony\Component\Console\Input\InputOption;
18 | use Symfony\Component\Console\Output\OutputInterface;
19 |
20 | /**
21 | * @author Sebastiaan Stok
22 | */
23 | class DeactivateUserCommand extends BaseDeactivateUserCommand
24 | {
25 | protected function configure()
26 | {
27 | parent::configure();
28 |
29 | $definition = $this->getDefinition();
30 | $definition->addOption(
31 | new InputOption('user-system', null, InputOption::VALUE_REQUIRED, 'The user-system to use')
32 | );
33 |
34 | $this
35 | ->setHelp(<<fos:user:deactivate command deactivates a user (will not be able to log in)
37 |
38 | php app/console fos:user:deactivate --user-system=acme_user matthieu
39 | EOT
40 | );
41 | }
42 |
43 | protected function interact(InputInterface $input, OutputInterface $output)
44 | {
45 | /** @var UserDiscriminatorInterface $discriminator */
46 | $discriminator = $this->getContainer()->get('rollerworks_multi_user.user_discriminator');
47 | $discriminator->setCurrentUser($input->getOption('user-system'));
48 |
49 | parent::interact($input, $output);
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/docs/user_manager.md:
--------------------------------------------------------------------------------
1 | About RollerworksMultiUserBundle User Manager
2 | =============================================
3 |
4 | The RollerworksMultiUserBundle only provides one User Manager class: `DelegatingUserManager`
5 | which delegates all calls to the actual User Manager of the current user-system.
6 |
7 | The `fos_user.user_manager` service should only be used when you want to manage the 'current' user-system,
8 | to manage a specific user-system you must refer to the `[service-prefix].user_manager` service like `acme_user.user_manager`.
9 |
10 | > The `[service-prefix]` is what you have configured for the user-system, in this case 'acme_user'
11 |
12 | Handling of user groups is pretty much the same, except that you use `acme_user.group_manager` for handling groups.
13 |
14 | **Note:**
15 |
16 | > Groups support must be enabled per user-system, by default the system uses the `NoopGroupManager` which does nothing.
17 | > See also: [Using Groups With FOSUserBundle](https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/doc/groups.md)
18 |
19 | ## Controller
20 |
21 | Because the FOSUserBundle Controllers always use the current user-system,
22 | you must either create your own or change the current user-system.
23 |
24 | The user-discriminator is available in the container as the rollerworks_multi_user.user_discriminator service.
25 |
26 | **Caution:** Make sure to use the user-system name for setCurrentUser(), and not the service-prefix.
27 |
28 | ```php
29 | $userDiscriminator = $container->get('rollerworks_multi_user.user_discriminator');
30 | $userDiscriminator->setCurrentUser('user-system-name');
31 |
32 | // Example
33 | $userDiscriminator->setCurrentUser('acme_user');
34 | ```
35 |
36 | **Note:**
37 |
38 | > As the group manager is connected to the user-system, this must also be done when
39 | > managing groups of another user-system.
40 |
--------------------------------------------------------------------------------
/src/Form/Type/ResettingFormType.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\Form\Type;
13 |
14 | use Symfony\Component\Form\AbstractType;
15 | use Symfony\Component\Form\FormBuilderInterface;
16 | use Symfony\Component\OptionsResolver\OptionsResolverInterface;
17 |
18 | class ResettingFormType extends AbstractType
19 | {
20 | /**
21 | * @var string
22 | */
23 | private $class;
24 |
25 | /**
26 | * @var string
27 | */
28 | private $typeName;
29 |
30 | /**
31 | * @param string $class The User class name
32 | * @param string $typeName The FormType name
33 | */
34 | public function __construct($class, $typeName)
35 | {
36 | $this->class = $class;
37 | $this->typeName = $typeName;
38 | }
39 |
40 | public function buildForm(FormBuilderInterface $builder, array $options)
41 | {
42 | $builder->add('plainPassword', 'repeated', array(
43 | 'type' => 'password',
44 | 'options' => array('translation_domain' => 'FOSUserBundle'),
45 | 'first_options' => array('label' => 'form.new_password'),
46 | 'second_options' => array('label' => 'form.new_password_confirmation'),
47 | 'invalid_message' => 'fos_user.password.mismatch',
48 | ));
49 | }
50 |
51 | public function setDefaultOptions(OptionsResolverInterface $resolver)
52 | {
53 | $resolver->setDefaults(array(
54 | 'data_class' => $this->class,
55 | 'intention' => 'resetting',
56 | ));
57 | }
58 |
59 | public function getName()
60 | {
61 | return $this->typeName;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/Command/ActivateUserCommand.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\Command;
13 |
14 | use FOS\UserBundle\Command\ActivateUserCommand as BaseActivateUserCommand;
15 | use Rollerworks\Bundle\MultiUserBundle\Model\UserDiscriminatorInterface;
16 | use Symfony\Component\Console\Input\InputInterface;
17 | use Symfony\Component\Console\Input\InputOption;
18 | use Symfony\Component\Console\Output\OutputInterface;
19 |
20 | /**
21 | * @author Sebastiaan Stok
22 | */
23 | class ActivateUserCommand extends BaseActivateUserCommand
24 | {
25 | /**
26 | * @see Command
27 | */
28 | protected function configure()
29 | {
30 | parent::configure();
31 |
32 | $definition = $this->getDefinition();
33 | $definition->addOption(
34 | new InputOption('user-system', null, InputOption::VALUE_REQUIRED, 'The user-system to use')
35 | );
36 |
37 | $this
38 | ->setHelp(<<fos:user:activate command activates a user (so they will be able to log in):
40 |
41 | php app/console fos:user:activate --user-system=acme_user matthieu
42 | EOT
43 | );
44 | }
45 |
46 | /**
47 | * @see Command
48 | */
49 | protected function interact(InputInterface $input, OutputInterface $output)
50 | {
51 | /** @var UserDiscriminatorInterface $discriminator */
52 | $discriminator = $this->getContainer()->get('rollerworks_multi_user.user_discriminator');
53 | $discriminator->setCurrentUser($input->getOption('user-system'));
54 |
55 | parent::interact($input, $output);
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/DependencyInjection/Compiler/OverrideServiceCompilerPass.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\DependencyInjection\Compiler;
13 |
14 | use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
15 | use Symfony\Component\DependencyInjection\ContainerBuilder;
16 |
17 | class OverrideServiceCompilerPass implements CompilerPassInterface
18 | {
19 | public function process(ContainerBuilder $container)
20 | {
21 | $this->changeService($container, 'fos_user.registration.form.factory', 'rollerworks_multi_user.registration.form.factory');
22 | $this->changeService($container, 'fos_user.resetting.form.factory', 'rollerworks_multi_user.resetting.form.factory');
23 | $this->changeService($container, 'fos_user.profile.form.factory', 'rollerworks_multi_user.profile.form.factory');
24 | $this->changeService($container, 'fos_user.change_password.form.factory', 'rollerworks_multi_user.change_password.form.factory');
25 | $this->changeService($container, 'fos_user.group.form.factory', 'rollerworks_multi_user.group.form.factory');
26 | }
27 |
28 | /**
29 | * @param string $serviceName
30 | * @param string $newServiceName
31 | */
32 | private function changeService(ContainerBuilder $container, $serviceName, $newServiceName)
33 | {
34 | if ($container->hasDefinition($serviceName) && $container->hasDefinition($newServiceName)) {
35 | $newService = $container->getDefinition($newServiceName);
36 |
37 | $container->removeDefinition($serviceName);
38 | $container->setDefinition($serviceName, $newService);
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/Doctrine/Orm/UserListener.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\Doctrine\Orm;
13 |
14 | use Doctrine\ORM\Event\LifecycleEventArgs;
15 | use Doctrine\ORM\Event\PreUpdateEventArgs;
16 | use Doctrine\ORM\Events;
17 | use FOS\UserBundle\Model\UserInterface;
18 | use Rollerworks\Bundle\MultiUserBundle\Doctrine\AbstractUserListener;
19 |
20 | /**
21 | * Doctrine ORM listener updating the canonical fields and the password.
22 | *
23 | * @author Sebastiaan Stok
24 | * @author Christophe Coevoet
25 | */
26 | class UserListener extends AbstractUserListener
27 | {
28 | public function getSubscribedEvents()
29 | {
30 | return array(
31 | Events::prePersist,
32 | Events::preUpdate,
33 | );
34 | }
35 |
36 | /**
37 | * @param LifecycleEventArgs $args
38 | */
39 | public function prePersist($args)
40 | {
41 | $object = $args->getEntity();
42 | if ($object instanceof UserInterface) {
43 | $this->updateUserFields($object);
44 | }
45 | }
46 |
47 | /**
48 | * @param PreUpdateEventArgs $args
49 | */
50 | public function preUpdate($args)
51 | {
52 | $object = $args->getEntity();
53 | if ($object instanceof UserInterface) {
54 | $this->updateUserFields($object);
55 | // We are doing a update, so we must force Doctrine to update the
56 | // changeset in case we changed something above
57 | $em = $args->getEntityManager();
58 | $uow = $em->getUnitOfWork();
59 | $meta = $em->getClassMetadata(get_class($object));
60 | $uow->recomputeSingleEntityChangeSet($meta, $object);
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/Doctrine/MongoDB/UserListener.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\Doctrine\MongoDB;
13 |
14 | use Doctrine\ODM\MongoDB\Event\LifecycleEventArgs;
15 | use Doctrine\ODM\MongoDB\Event\PreUpdateEventArgs;
16 | use Doctrine\ODM\MongoDB\Events;
17 | use FOS\UserBundle\Model\UserInterface;
18 | use Rollerworks\Bundle\MultiUserBundle\Doctrine\AbstractUserListener;
19 |
20 | /**
21 | * Doctrine MongoDB ODM listener updating the canonical fields and the password.
22 | *
23 | * @author Sebastiaan Stok
24 | * @author Christophe Coevoet
25 | */
26 | class UserListener extends AbstractUserListener
27 | {
28 | public function getSubscribedEvents()
29 | {
30 | return array(
31 | Events::prePersist,
32 | Events::preUpdate,
33 | );
34 | }
35 |
36 | /**
37 | * @param LifecycleEventArgs $args
38 | */
39 | public function prePersist($args)
40 | {
41 | $object = $args->getDocument();
42 | if ($object instanceof UserInterface) {
43 | $this->updateUserFields($object);
44 | }
45 | }
46 |
47 | /**
48 | * @param PreUpdateEventArgs $args
49 | */
50 | public function preUpdate($args)
51 | {
52 | $object = $args->getDocument();
53 | if ($object instanceof UserInterface) {
54 | $this->updateUserFields($object);
55 | // We are doing a update, so we must force Doctrine to update the
56 | // changeset in case we changed something above
57 | $dm = $args->getDocumentManager();
58 | $uow = $dm->getUnitOfWork();
59 | $meta = $dm->getClassMetadata(get_class($object));
60 | $uow->recomputeSingleDocumentChangeSet($meta, $object);
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/Command/ChangePasswordCommand.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\Command;
13 |
14 | use FOS\UserBundle\Command\ChangePasswordCommand as BaseChangePasswordCommand;
15 | use Rollerworks\Bundle\MultiUserBundle\Model\UserDiscriminatorInterface;
16 | use Symfony\Component\Console\Input\InputInterface;
17 | use Symfony\Component\Console\Input\InputOption;
18 | use Symfony\Component\Console\Output\OutputInterface;
19 |
20 | /**
21 | * @author Sebastiaan Stok
22 | */
23 | class ChangePasswordCommand extends BaseChangePasswordCommand
24 | {
25 | protected function configure()
26 | {
27 | parent::configure();
28 |
29 | $definition = $this->getDefinition();
30 | $definition->addOption(
31 | new InputOption('user-system', null, InputOption::VALUE_REQUIRED, 'The user-system to use')
32 | );
33 |
34 | $this
35 | ->setHelp(<<fos:user:change-password command changes the password of a user:
37 |
38 | php app/console fos:user:change-password --user-system=acme_user matthieu
39 |
40 | This interactive shell will first ask you for a password.
41 |
42 | You can alternatively specify the password as a second argument:
43 |
44 | php app/console fos:user:change-password --user-system=acme_user matthieu mypassword
45 |
46 | EOT
47 | );
48 | }
49 |
50 | protected function interact(InputInterface $input, OutputInterface $output)
51 | {
52 | /** @var UserDiscriminatorInterface $discriminator */
53 | $discriminator = $this->getContainer()->get('rollerworks_multi_user.user_discriminator');
54 | $discriminator->setCurrentUser($input->getOption('user-system'));
55 |
56 | parent::interact($input, $output);
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/EventListener/RequestListener.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\EventListener;
13 |
14 | use Rollerworks\Bundle\MultiUserBundle\Model\UserDiscriminatorInterface;
15 | use Symfony\Component\HttpFoundation\RequestMatcherInterface;
16 | use Symfony\Component\HttpKernel\Event\GetResponseEvent;
17 |
18 | /**
19 | * Tries to determine the current user-system.
20 | *
21 | * @author Sebastiaan Stok
22 | */
23 | class RequestListener
24 | {
25 | /**
26 | * @var UserDiscriminatorInterface
27 | */
28 | protected $userDiscriminator;
29 |
30 | /**
31 | * @var RequestMatcherInterface[]
32 | */
33 | protected $users;
34 |
35 | /**
36 | * @param UserDiscriminatorInterface $userDiscriminator
37 | */
38 | public function __construct(UserDiscriminatorInterface $userDiscriminator)
39 | {
40 | $this->userDiscriminator = $userDiscriminator;
41 | $this->users = array();
42 | }
43 |
44 | /**
45 | * @param string $name
46 | * @param RequestMatcherInterface $requestMatcher
47 | */
48 | public function addUser($name, RequestMatcherInterface $requestMatcher)
49 | {
50 | $this->users[$name] = $requestMatcher;
51 | }
52 |
53 | /**
54 | * {@inheritdoc}
55 | */
56 | public function onKernelRequest(GetResponseEvent $event)
57 | {
58 | // Already set
59 | if (null !== $this->userDiscriminator->getCurrentUser()) {
60 | return;
61 | }
62 |
63 | $request = $event->getRequest();
64 | foreach ($this->users as $name => $requestMatcher) {
65 | if ($requestMatcher->matches($request)) {
66 | $this->userDiscriminator->setCurrentUser($name);
67 |
68 | return;
69 | }
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/Form/FormFactory.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\Form;
13 |
14 | use FOS\UserBundle\Form\Factory\FactoryInterface;
15 | use Rollerworks\Bundle\MultiUserBundle\Model\UserDiscriminatorInterface;
16 | use Symfony\Component\Form\FormFactoryInterface;
17 | use Symfony\Component\Form\FormInterface;
18 |
19 | /**
20 | * @author Sebastiaan Stok
21 | * @author Leonardo Proietti
22 | */
23 | class FormFactory implements FactoryInterface
24 | {
25 | /**
26 | * @var UserDiscriminatorInterface
27 | */
28 | private $userDiscriminator;
29 |
30 | /**
31 | * @var FormFactoryInterface
32 | */
33 | private $formFactory;
34 |
35 | /**
36 | * @var string
37 | */
38 | private $type;
39 |
40 | /**
41 | * @param FormFactoryInterface $formFactory
42 | * @param string $type Form type name
43 | */
44 | public function __construct(FormFactoryInterface $formFactory, $type)
45 | {
46 | $this->formFactory = $formFactory;
47 | $this->type = $type;
48 | }
49 |
50 | /**
51 | * @param UserDiscriminatorInterface $userDiscriminator
52 | */
53 | public function setUserDiscriminator($userDiscriminator)
54 | {
55 | $this->userDiscriminator = $userDiscriminator;
56 | }
57 |
58 | /**
59 | * @return FormInterface
60 | */
61 | public function createForm()
62 | {
63 | $user = $this->userDiscriminator->getCurrentUserConfig();
64 | $type = $user->getFormType($this->type);
65 | $name = $user->getFormName($this->type);
66 | $validationGroups = $user->getFormValidationGroups($this->type);
67 |
68 | return $this->formFactory->createNamed($name, $type, null, array('validation_groups' => $validationGroups));
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/Resources/skeleton/bundle/Configuration.php.twig:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace {{
13 |
14 | namespace }}\DependencyInjection;
15 |
16 | { % block use_statements % }
17 | use Rollerworks\Bundle\MultiUserBundle\DependencyInjection\Configuration as UserConfiguration;
18 | use Symfony\Component\Config\Definition\Builder\TreeBuilder;
19 | use Symfony\Component\Config\Definition\ConfigurationInterface;
20 |
21 | { % endblock use_statements % }
22 |
23 | /*
24 | {% block phpdoc_class_header %}
25 | * This is the class that validates and merges configuration from your app/config files
26 | {% endblock phpdoc_class_header %}
27 | *
28 | * To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html#cookbook-bundles-extension-config-class}
29 | * To learn more about the user-configuration see {@link https://github.com/rollerworks/RollerworksMultiUserBundle/blob/master/docs/index.md#33-make-your-bundle-configurable}
30 | */
31 | { % block class_definition % }
32 | class Configuration implements ConfigurationInterface
33 | {
34 | % endblock class_definition %
35 | }
36 | {
37 | { % block class_body % }
38 | /**
39 | * {@inheritdoc}
40 | */
41 | public function getConfigTreeBuilder()
42 | {
43 | $treeBuilder = new TreeBuilder();
44 | $rootNode = $treeBuilder->root('{{ extension_alias }}');
45 |
46 | $configuration = new UserConfiguration();
47 |
48 | // Add the UserConfiguration tree
49 | // Enables everything except group
50 | $configuration->addUserConfig($rootNode, UserConfiguration::CONFIG_ALL ^ UserConfiguration::CONFIG_SECTION_GROUP);
51 |
52 | // Here you should define the parameters that are allowed to
53 | // configure your bundle. See the documentation linked above for
54 | // more information on that topic.
55 |
56 | return $treeBuilder;
57 | }
58 | { % endblock class_body % }
59 | }
60 |
--------------------------------------------------------------------------------
/scripts/generate-events.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | if (!file_exists(__DIR__.'/../vendor/autoload.php')) {
13 | throw new \RuntimeException('Did not find vendor/autoload.php. Please Install vendors using command: composer.phar install --dev');
14 | }
15 |
16 | /**
17 | * @var ClassLoader
18 | */
19 | $loader = require_once __DIR__.'/../vendor/autoload.php';
20 |
21 | $eventsClass = new \ReflectionClass('FOS\UserBundle\FOSUserEvents');
22 | $events = $eventsClass->getConstants();
23 |
24 | $underscoreToCamelCase = function ($string) {
25 | $string = strtolower($string);
26 |
27 | return preg_replace_callback('/_([a-z])/', function ($c) {
28 | return strtoupper($c[1]);
29 | }, $string);
30 | };
31 |
32 | $date = date('Y-m-d');
33 |
34 | echo << $eventName) {
42 | $event = ucfirst($underscoreToCamelCase($event));
43 | $eventName = substr($eventName, 8);
44 |
45 | echo <<userDiscriminator->getCurrentUser()) {
50 | \$this->eventDispatcher->dispatch(\$userSys . '$eventName', \$e);
51 | }
52 | }
53 |
54 | EOT;
55 | }
56 |
57 | echo << $eventName) {
71 | $eventFunc = ucfirst($underscoreToCamelCase($event));
72 |
73 | echo << 'dispatch$eventFunc',
75 |
76 | EOT;
77 | }
78 |
79 | echo <<
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\EventListener;
13 |
14 | use FOS\UserBundle\Event\FormEvent;
15 | use FOS\UserBundle\Event\GetResponseUserEvent;
16 | use FOS\UserBundle\FOSUserEvents;
17 | use Rollerworks\Bundle\MultiUserBundle\Model\UserDiscriminatorInterface;
18 | use Symfony\Component\EventDispatcher\EventSubscriberInterface;
19 | use Symfony\Component\HttpFoundation\RedirectResponse;
20 | use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
21 |
22 | class RegistrationListener implements EventSubscriberInterface
23 | {
24 | private $router;
25 | private $userDiscriminator;
26 |
27 | public function __construct(UrlGeneratorInterface $router, UserDiscriminatorInterface $userDiscriminator)
28 | {
29 | $this->router = $router;
30 | $this->userDiscriminator = $userDiscriminator;
31 | }
32 |
33 | public static function getSubscribedEvents()
34 | {
35 | return array(
36 | FOSUserEvents::REGISTRATION_CONFIRM => array('onRegistrationConfirm', 1),
37 | FOSUserEvents::REGISTRATION_SUCCESS => array('onRegistrationSuccess', 1),
38 | );
39 | }
40 |
41 | public function onRegistrationSuccess(FormEvent $event)
42 | {
43 | if (null === $event->getResponse()) {
44 | $url = $this->router->generate($this->userDiscriminator->getCurrentUserConfig()->getRoutePrefix().'_registration_confirmed');
45 | $event->setResponse(new RedirectResponse($url));
46 | }
47 | }
48 |
49 | public function onRegistrationConfirm(GetResponseUserEvent $event)
50 | {
51 | if (null === $event->getResponse()) {
52 | $url = $this->router->generate($this->userDiscriminator->getCurrentUserConfig()->getRoutePrefix().'_registration_confirmed');
53 | $event->setResponse(new RedirectResponse($url));
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/Form/Type/RegistrationFormType.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\Form\Type;
13 |
14 | use Symfony\Component\Form\AbstractType;
15 | use Symfony\Component\Form\FormBuilderInterface;
16 | use Symfony\Component\OptionsResolver\OptionsResolverInterface;
17 |
18 | class RegistrationFormType extends AbstractType
19 | {
20 | /**
21 | * @var string
22 | */
23 | private $class;
24 |
25 | /**
26 | * @var string
27 | */
28 | private $typeName;
29 |
30 | /**
31 | * @param string $class The User class name
32 | * @param string $typeName The FormType name
33 | */
34 | public function __construct($class, $typeName)
35 | {
36 | $this->class = $class;
37 | $this->typeName = $typeName;
38 | }
39 |
40 | public function buildForm(FormBuilderInterface $builder, array $options)
41 | {
42 | $builder
43 | ->add('email', 'email', array('label' => 'form.email', 'translation_domain' => 'FOSUserBundle'))
44 | ->add('username', null, array('label' => 'form.username', 'translation_domain' => 'FOSUserBundle'))
45 | ->add('plainPassword', 'repeated', array(
46 | 'type' => 'password',
47 | 'options' => array('translation_domain' => 'FOSUserBundle'),
48 | 'first_options' => array('label' => 'form.password'),
49 | 'second_options' => array('label' => 'form.password_confirmation'),
50 | 'invalid_message' => 'fos_user.password.mismatch',
51 | ))
52 | ;
53 | }
54 |
55 | public function setDefaultOptions(OptionsResolverInterface $resolver)
56 | {
57 | $resolver->setDefaults(array(
58 | 'data_class' => $this->class,
59 | 'intention' => 'registration',
60 | ));
61 | }
62 |
63 | public function getName()
64 | {
65 | return $this->typeName;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/EventListener/ResettingListener.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\EventListener;
13 |
14 | use FOS\UserBundle\Event\FormEvent;
15 | use FOS\UserBundle\Event\GetResponseUserEvent;
16 | use FOS\UserBundle\FOSUserEvents;
17 | use Rollerworks\Bundle\MultiUserBundle\Model\UserDiscriminatorInterface;
18 | use Symfony\Component\EventDispatcher\EventSubscriberInterface;
19 | use Symfony\Component\HttpFoundation\RedirectResponse;
20 | use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
21 |
22 | class ResettingListener implements EventSubscriberInterface
23 | {
24 | private $router;
25 | private $userDiscriminator;
26 |
27 | public function __construct(UrlGeneratorInterface $router, UserDiscriminatorInterface $userDiscriminator)
28 | {
29 | $this->router = $router;
30 | $this->userDiscriminator = $userDiscriminator;
31 | }
32 |
33 | public static function getSubscribedEvents()
34 | {
35 | return array(
36 | FOSUserEvents::RESETTING_RESET_INITIALIZE => array('onResettingResetInitialize', 1),
37 | FOSUserEvents::RESETTING_RESET_SUCCESS => array('onResettingResetSuccess', 1),
38 | );
39 | }
40 |
41 | public function onResettingResetInitialize(GetResponseUserEvent $event)
42 | {
43 | $user = $this->userDiscriminator->getCurrentUserConfig();
44 |
45 | $tokenTtl = $user->getConfig('resetting.token_ttl', 86400);
46 |
47 | if (!$event->getUser()->isPasswordRequestNonExpired($tokenTtl)) {
48 | $event->setResponse(new RedirectResponse($this->router->generate($user->getRoutePrefix().'_resetting_request')));
49 |
50 | // Prevent the FOSUserBundle from overwriting
51 | $event->stopPropagation();
52 | }
53 | }
54 |
55 | public function onResettingResetSuccess(FormEvent $event)
56 | {
57 | $event->setResponse(new RedirectResponse($this->router->generate($this->userDiscriminator->getCurrentUserConfig()->getRoutePrefix().'_profile_show')));
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "rollerworks/multi-user-bundle",
3 | "type": "symfony-bundle",
4 | "description": "Multi user management for the FOSUserBundle",
5 | "keywords": ["rollerworks", "multi", "user", "bundle", "FOSUserBundle"],
6 | "license": "MIT",
7 | "authors": [
8 | {
9 | "name": "Sebastiaan Stok",
10 | "email": "s.stok@rollercapes.net"
11 | },
12 | {
13 | "name": "Contributors",
14 | "homepage": "https://github.com/rollerworks/RollerworksMultiUserBundle/graphs/contributors"
15 | }
16 | ],
17 | "minimum-stability": "dev",
18 | "prefer-stable": true,
19 | "require": {
20 | "php": ">=5.3.3",
21 | "symfony/framework-bundle": "~2.3|~3.0",
22 | "symfony/proxy-manager-bridge": "~2.3|~3.0",
23 | "ocramius/proxy-manager": "~0.4|~1.0",
24 | "symfony/finder": "~2.3|~3.0",
25 | "friendsofsymfony/user-bundle": "~2.0@dev,>2.0.0-alpha3",
26 | "rollerworks/sf-container-injector": "~1.0"
27 | },
28 | "require-dev": {
29 | "twig/twig": "~1.5",
30 | "doctrine/doctrine-bundle": "~1.2",
31 | "doctrine/orm": "^2.2.3",
32 | "swiftmailer/swiftmailer": ">=4.3,<6.0",
33 | "symfony/yaml": "~2.3|~3.0",
34 | "symfony/validator": "~2.3|~3.0",
35 | "symfony/twig-bundle": "~2.3|~3.0",
36 | "symfony/monolog-bundle": "~2.3",
37 | "symfony/swiftmailer-bundle": "~2.3",
38 | "symfony/web-profiler-bundle": "~2.3|~3.0",
39 | "symfony/browser-kit": "~2.3|~3.0",
40 | "symfony/css-selector": "~2.3|~3.0",
41 | "symfony/process": "~2.3|~3.0",
42 | "symfony/expression-language": "~2.4|~3.0",
43 | "matthiasnoback/symfony-config-test": "^0.1.1",
44 | "sensio/generator-bundle": "~2.3|~3.0"
45 | },
46 | "conflict": {
47 | "pugx/multi-user-bundle": "*"
48 | },
49 | "autoload": {
50 | "psr-4": {
51 | "Rollerworks\\Bundle\\MultiUserBundle\\": "src/"
52 | }
53 | },
54 | "autoload-dev": {
55 | "psr-4": {
56 | "Rollerworks\\Bundle\\MultiUserBundle\\Tests\\": "tests/"
57 | }
58 | },
59 | "extra": {
60 | "branch-alias": {
61 | "dev-master": "1.1-dev"
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/Command/CreateUserCommand.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\Command;
13 |
14 | use FOS\UserBundle\Command\CreateUserCommand as BaseCreateUserCommand;
15 | use Rollerworks\Bundle\MultiUserBundle\Model\UserDiscriminatorInterface;
16 | use Symfony\Component\Console\Input\InputInterface;
17 | use Symfony\Component\Console\Input\InputOption;
18 | use Symfony\Component\Console\Output\OutputInterface;
19 |
20 | /**
21 | * @author Sebastiaan Stok
22 | */
23 | class CreateUserCommand extends BaseCreateUserCommand
24 | {
25 | protected function configure()
26 | {
27 | parent::configure();
28 |
29 | $definition = $this->getDefinition();
30 | $definition->addOption(
31 | new InputOption('user-system', null, InputOption::VALUE_REQUIRED, 'The user-system to use')
32 | );
33 |
34 | $this
35 | ->setHelp(<<fos:user:create command creates a user:
37 |
38 | php app/console fos:user:create --user-system=acme_user matthieu
39 |
40 | This interactive shell will ask you for an email and then a password.
41 |
42 | You can alternatively specify the email and password as the second and third arguments:
43 |
44 | php app/console fos:user:create --user-system=acme_user matthieu matthieu@example.com mypassword
45 |
46 | You can create a super admin via the super-admin flag:
47 |
48 | php app/console fos:user:create admin --super-admin
49 |
50 | You can create an inactive user (will not be able to log in):
51 |
52 | php app/console fos:user:create thibault --inactive
53 |
54 | EOT
55 | );
56 | }
57 |
58 | protected function interact(InputInterface $input, OutputInterface $output)
59 | {
60 | /** @var UserDiscriminatorInterface $discriminator */
61 | $discriminator = $this->getContainer()->get('rollerworks_multi_user.user_discriminator');
62 | $discriminator->setCurrentUser($input->getOption('user-system'));
63 |
64 | parent::interact($input, $output);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/Command/DemoteUserCommand.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\Command;
13 |
14 | use FOS\UserBundle\Command\DemoteUserCommand as BaseDemoteUserCommand;
15 | use Rollerworks\Bundle\MultiUserBundle\Model\UserDiscriminatorInterface;
16 | use Symfony\Component\Console\Input\InputArgument;
17 | use Symfony\Component\Console\Input\InputDefinition;
18 | use Symfony\Component\Console\Input\InputInterface;
19 | use Symfony\Component\Console\Input\InputOption;
20 | use Symfony\Component\Console\Output\OutputInterface;
21 |
22 | /**
23 | * @author Sebastiaan Stok
24 | */
25 | class DemoteUserCommand extends BaseDemoteUserCommand
26 | {
27 | protected function configure()
28 | {
29 | parent::configure();
30 |
31 | $definition = new InputDefinition();
32 | $definition->setDefinition(array(
33 | new InputArgument('username', InputArgument::REQUIRED, 'The username'),
34 | new InputArgument('role', InputArgument::OPTIONAL, 'The role'),
35 | new InputOption('user-system', null, InputOption::VALUE_REQUIRED, 'The user-system to use'),
36 | new InputOption('super', null, InputOption::VALUE_NONE, 'Instead specifying role, use this to quickly add the super administrator role'),
37 | ));
38 |
39 | $this->setDefinition($definition);
40 |
41 | $this
42 | ->setHelp(<<fos:user:demote command demotes a user by removing a role
44 |
45 | php app/console fos:user:demote --user-system=acme_user matthieu ROLE_CUSTOM
46 | php app/console fos:user:demote --user-system=acme_user --super matthieu
47 | EOT
48 | );
49 | }
50 |
51 | protected function interact(InputInterface $input, OutputInterface $output)
52 | {
53 | /** @var UserDiscriminatorInterface $discriminator */
54 | $discriminator = $this->getContainer()->get('rollerworks_multi_user.user_discriminator');
55 | $discriminator->setCurrentUser($input->getOption('user-system'));
56 |
57 | parent::interact($input, $output);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/Form/Type/ChangePasswordFormType.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\Form\Type;
13 |
14 | use Symfony\Component\Form\AbstractType;
15 | use Symfony\Component\Form\FormBuilderInterface;
16 | use Symfony\Component\OptionsResolver\OptionsResolverInterface;
17 | use Symfony\Component\Security\Core\Validator\Constraints\UserPassword;
18 |
19 | class ChangePasswordFormType extends AbstractType
20 | {
21 | /**
22 | * @var string
23 | */
24 | private $class;
25 |
26 | /**
27 | * @var string
28 | */
29 | private $typeName;
30 |
31 | /**
32 | * @param string $class The User class name
33 | * @param string $typeName The FormType name
34 | */
35 | public function __construct($class, $typeName)
36 | {
37 | $this->class = $class;
38 | $this->typeName = $typeName;
39 | }
40 |
41 | public function buildForm(FormBuilderInterface $builder, array $options)
42 | {
43 | $constraint = new UserPassword();
44 |
45 | $builder
46 | ->add('current_password', 'password', array(
47 | 'label' => 'form.current_password',
48 | 'translation_domain' => 'FOSUserBundle',
49 | 'mapped' => false,
50 | 'constraints' => $constraint,
51 | ))
52 | ->add('plainPassword', 'repeated', array(
53 | 'type' => 'password',
54 | 'options' => array('translation_domain' => 'FOSUserBundle'),
55 | 'first_options' => array('label' => 'form.new_password'),
56 | 'second_options' => array('label' => 'form.new_password_confirmation'),
57 | 'invalid_message' => 'fos_user.password.mismatch',
58 | ));
59 | }
60 |
61 | public function setDefaultOptions(OptionsResolverInterface $resolver)
62 | {
63 | $resolver->setDefaults(array(
64 | 'data_class' => $this->class,
65 | 'intention' => 'change_password',
66 | ));
67 | }
68 |
69 | public function getName()
70 | {
71 | return $this->typeName;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/Model/DelegatingGroupManager.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\Model;
13 |
14 | use FOS\UserBundle\Model\GroupInterface;
15 | use FOS\UserBundle\Model\GroupManagerInterface;
16 |
17 | /**
18 | * DelegatingGroupManager selects a GroupManager for the current user.
19 | *
20 | * Please don't use this manager as its only used for the original controllers.
21 | *
22 | * @author Sebastiaan Stok
23 | */
24 | class DelegatingGroupManager implements GroupManagerInterface
25 | {
26 | private $userDiscriminator;
27 |
28 | public function __construct(UserDiscriminatorInterface $userDiscriminator)
29 | {
30 | $this->userDiscriminator = $userDiscriminator;
31 | }
32 |
33 | /**
34 | * @return UserDiscriminatorInterface
35 | */
36 | public function getUserDiscriminator()
37 | {
38 | return $this->userDiscriminator;
39 | }
40 |
41 | public function getClass()
42 | {
43 | return $this->userDiscriminator->getCurrentUserConfig()->getGroupManager()->getClass();
44 | }
45 |
46 | public function createGroup($name)
47 | {
48 | return $this->userDiscriminator->getCurrentUserConfig()->getGroupManager()->createGroup($name);
49 | }
50 |
51 | public function deleteGroup(GroupInterface $group)
52 | {
53 | $this->userDiscriminator->getCurrentUserConfig()->getGroupManager()->deleteGroup($group);
54 | }
55 |
56 | public function findGroupBy(array $criteria)
57 | {
58 | return $this->userDiscriminator->getCurrentUserConfig()->getGroupManager()->findGroupBy($criteria);
59 | }
60 |
61 | public function findGroupByName($name)
62 | {
63 | return $this->userDiscriminator->getCurrentUserConfig()->getGroupManager()->findGroupByName($name);
64 | }
65 |
66 | public function findGroups()
67 | {
68 | return $this->userDiscriminator->getCurrentUserConfig()->getGroupManager()->findGroups();
69 | }
70 |
71 | public function updateGroup(GroupInterface $group)
72 | {
73 | $this->userDiscriminator->getCurrentUserConfig()->getGroupManager()->updateGroup($group);
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/Command/PromoteUserCommand.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\Command;
13 |
14 | use FOS\UserBundle\Command\PromoteUserCommand as BasePromoteUserCommand;
15 | use Rollerworks\Bundle\MultiUserBundle\Model\UserDiscriminatorInterface;
16 | use Symfony\Component\Console\Input\InputArgument;
17 | use Symfony\Component\Console\Input\InputDefinition;
18 | use Symfony\Component\Console\Input\InputInterface;
19 | use Symfony\Component\Console\Input\InputOption;
20 | use Symfony\Component\Console\Output\OutputInterface;
21 |
22 | /**
23 | * @author Sebastiaan Stok
24 | */
25 | class PromoteUserCommand extends BasePromoteUserCommand
26 | {
27 | /**
28 | * @see Command
29 | */
30 | protected function configure()
31 | {
32 | parent::configure();
33 |
34 | $definition = new InputDefinition();
35 | $definition->setDefinition(array(
36 | new InputArgument('username', InputArgument::REQUIRED, 'The username'),
37 | new InputArgument('role', InputArgument::OPTIONAL, 'The role'),
38 | new InputOption('user-system', null, InputOption::VALUE_REQUIRED, 'The user-system to use'),
39 | new InputOption('super', null, InputOption::VALUE_NONE, 'Instead specifying role, use this to quickly add the super administrator role'),
40 | ));
41 |
42 | $this->setDefinition($definition);
43 | $this
44 | ->setHelp(<<fos:user:promote command promotes a user by adding a role
46 |
47 | php app/console fos:user:promote --user-system=acme_user matthieu ROLE_CUSTOM
48 | php app/console fos:user:promote --user-system=acme_user --super matthieu
49 | EOT
50 | );
51 | }
52 |
53 | protected function interact(InputInterface $input, OutputInterface $output)
54 | {
55 | /** @var UserDiscriminatorInterface $discriminator */
56 | $discriminator = $this->getContainer()->get('rollerworks_multi_user.user_discriminator');
57 | $discriminator->setCurrentUser($input->getOption('user-system'));
58 |
59 | parent::interact($input, $output);
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/docs/overriding_forms.md:
--------------------------------------------------------------------------------
1 | Overriding Default FOSUserBundle Forms
2 | ======================================
3 |
4 | See [Overriding Default FOSUserBundle Forms](https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/doc/overriding_forms.md)
5 | for full details.
6 |
7 | **Note:**
8 |
9 | > Each user-system must have its own form-types, you can not reuse the form types of UserA for UserB
10 | > as a form form-type can only be registered once, make sure `getName()` returns a unique name.
11 |
12 | Replace the `%fos_user.model.user.class%` with `%[service-prefix].model.user.class%` to get the correct model class.
13 |
14 | > `[service-prefix]` is what you have configured for the user-system.
15 | > And don't forget to do the same for `%fos_user.model.group.class%`
16 |
17 | ### Automatic registering
18 |
19 | The `UserServicesFactory` allows automatic registering of the Form service definition,
20 | to do this set the `class` configuration at the correct section with `UserServicesFactory::create()`.
21 |
22 | > Unless you have added additional constructor parameters to your class, this is preferred way of registering a type.
23 |
24 | ```php
25 |
26 | create('acme_user', array(
41 | array(
42 | // ...
43 |
44 | 'registration' => array(
45 | 'form' => array(
46 | 'type' => 'acme_user_registration',
47 | 'class' => 'Acme\UserBundle\Form\Type\RegistrationFormType',
48 | 'name' => 'acme_user_registration_form',
49 | )
50 | )
51 | )
52 | ));
53 | }
54 | }
55 | ```
56 |
57 | This will automatically register the `acme_user.registration.form.type` service with the correct user class.
58 |
59 | *Caution:* the `type` configuration is always required and must be the same as the returned value
60 | of the Form's `getName()` method.
61 |
--------------------------------------------------------------------------------
/src/Form/Type/ProfileFormType.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\Form\Type;
13 |
14 | use Symfony\Component\Form\AbstractType;
15 | use Symfony\Component\Form\FormBuilderInterface;
16 | use Symfony\Component\OptionsResolver\OptionsResolverInterface;
17 | use Symfony\Component\Security\Core\Validator\Constraints\UserPassword;
18 |
19 | class ProfileFormType extends AbstractType
20 | {
21 | /**
22 | * @var string
23 | */
24 | private $class;
25 |
26 | /**
27 | * @var string
28 | */
29 | private $typeName;
30 |
31 | /**
32 | * @param string $class The User class name
33 | * @param string $typeName The FormType name
34 | */
35 | public function __construct($class, $typeName)
36 | {
37 | $this->class = $class;
38 | $this->typeName = $typeName;
39 | }
40 |
41 | public function buildForm(FormBuilderInterface $builder, array $options)
42 | {
43 | $constraint = new UserPassword();
44 | $this->buildUserForm($builder, $options);
45 |
46 | $builder->add('current_password', 'password', array(
47 | 'label' => 'form.current_password',
48 | 'translation_domain' => 'FOSUserBundle',
49 | 'mapped' => false,
50 | 'constraints' => $constraint,
51 | ));
52 | }
53 |
54 | public function setDefaultOptions(OptionsResolverInterface $resolver)
55 | {
56 | $resolver->setDefaults(array(
57 | 'data_class' => $this->class,
58 | 'intention' => 'profile',
59 | ));
60 | }
61 |
62 | public function getName()
63 | {
64 | return $this->typeName;
65 | }
66 |
67 | /**
68 | * Builds the embedded form representing the user.
69 | *
70 | * @param FormBuilderInterface $builder
71 | * @param array $options
72 | */
73 | protected function buildUserForm(FormBuilderInterface $builder, array $options)
74 | {
75 | $builder
76 | ->add('username', null, array('label' => 'form.username', 'translation_domain' => 'FOSUserBundle'))
77 | ->add('email', 'email', array('label' => 'form.email', 'translation_domain' => 'FOSUserBundle'))
78 | ;
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/Resources/config/container/services.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 | Symfony\Component\HttpFoundation\RequestMatcher
9 | Rollerworks\Bundle\MultiUserBundle\Model\UserDiscriminator
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/src/EventListener/GroupListener.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\EventListener;
13 |
14 | use FOS\UserBundle\Event\FormEvent;
15 | use FOS\UserBundle\FOSUserEvents;
16 | use Rollerworks\Bundle\MultiUserBundle\Model\UserDiscriminatorInterface;
17 | use Symfony\Component\EventDispatcher\EventSubscriberInterface;
18 | use Symfony\Component\HttpFoundation\RedirectResponse;
19 | use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
20 |
21 | class GroupListener implements EventSubscriberInterface
22 | {
23 | private $router;
24 | private $userDiscriminator;
25 |
26 | public function __construct(UrlGeneratorInterface $router, UserDiscriminatorInterface $userDiscriminator)
27 | {
28 | $this->router = $router;
29 | $this->userDiscriminator = $userDiscriminator;
30 | }
31 |
32 | public static function getSubscribedEvents()
33 | {
34 | return array(
35 | FOSUserEvents::GROUP_CREATE_SUCCESS => array('onGroupCreateSuccess', 1),
36 | FOSUserEvents::GROUP_EDIT_SUCCESS => array('onGroupEditSuccess', 1),
37 | FOSUserEvents::GROUP_DELETE_COMPLETED => array('onGroupDeleteCompleted', 1),
38 | );
39 | }
40 |
41 | public function onGroupCreateSuccess(FormEvent $event)
42 | {
43 | if (null === $event->getResponse()) {
44 | $url = $this->router->generate($this->userDiscriminator->getCurrentUserConfig()->getRoutePrefix().'_group_show', array('groupName' => $event->getForm()->getData()->getName()));
45 | $event->setResponse(new RedirectResponse($url));
46 | }
47 | }
48 |
49 | public function onGroupEditSuccess(FormEvent $event)
50 | {
51 | if (null === $event->getResponse()) {
52 | $url = $this->router->generate($this->userDiscriminator->getCurrentUserConfig()->getRoutePrefix().'_group_show', array('groupName' => $event->getForm()->getData()->getName()));
53 | $event->setResponse(new RedirectResponse($url));
54 | }
55 | }
56 |
57 | public function onGroupDeleteCompleted(FormEvent $event)
58 | {
59 | if ($event->getResponse() instanceof RedirectResponse) {
60 | $url = $this->router->generate($this->userDiscriminator->getCurrentUserConfig()->getRoutePrefix().'_group_list');
61 | $event->setResponse(new RedirectResponse($url));
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/Routing/UserDiscriminatorUrlGenerator.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\Routing;
13 |
14 | use Rollerworks\Bundle\MultiUserBundle\Model\UserDiscriminatorInterface;
15 | use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
16 | use Symfony\Component\Routing\RequestContext;
17 | use Symfony\Component\Routing\RouterInterface;
18 |
19 | /**
20 | * Changes the route name to a userDiscriminated version
21 | * and delegates to the real generator.
22 | *
23 | * @author Sebastiaan Stok
24 | */
25 | class UserDiscriminatorUrlGenerator implements RouterInterface
26 | {
27 | private $userDiscriminator;
28 | private $generator;
29 | private $prefix;
30 | private $prefixLen;
31 |
32 | /**
33 | * @param UserDiscriminatorInterface $userDiscriminator
34 | * @param UrlGeneratorInterface $generator
35 | * @param string $prefix
36 | */
37 | public function __construct(UserDiscriminatorInterface $userDiscriminator, UrlGeneratorInterface $generator, $prefix = 'fos_user')
38 | {
39 | $this->userDiscriminator = $userDiscriminator;
40 | $this->generator = $generator;
41 | $this->prefix = $prefix;
42 | $this->prefixLen = strlen($prefix);
43 | }
44 |
45 | /**
46 | * @codeCoverageIgnore
47 | */
48 | public function setContext(RequestContext $context)
49 | {
50 | // noop
51 | }
52 |
53 | /**
54 | * @codeCoverageIgnore
55 | */
56 | public function getContext()
57 | {
58 | // noop
59 | }
60 |
61 | /**
62 | * {@inheritdoc}
63 | */
64 | public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH)
65 | {
66 | if (substr($name, 0, $this->prefixLen) === $this->prefix) {
67 | $name = $this->userDiscriminator->getCurrentUserConfig()->getRoutePrefix().substr($name, $this->prefixLen);
68 | }
69 |
70 | return $this->generator->generate($name, $parameters, $referenceType);
71 | }
72 |
73 | /**
74 | * @codeCoverageIgnore
75 | */
76 | public function getRouteCollection()
77 | {
78 | // noop
79 | }
80 |
81 | /**
82 | * @param string $pathinfo
83 | *
84 | *
85 | * @codeCoverageIgnore
86 | */
87 | public function match($pathinfo)
88 | {
89 | // noop
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/Model/UserDiscriminator.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\Model;
13 |
14 | use Rollerworks\Bundle\MultiUserBundle\Exception\NoActiveUserSystemException;
15 | use Symfony\Component\Form\Exception\UnexpectedTypeException;
16 |
17 | /**
18 | * @author Sebastiaan Stok
19 | */
20 | class UserDiscriminator implements UserDiscriminatorInterface
21 | {
22 | /**
23 | * @var UserConfig[]
24 | */
25 | protected $users = array();
26 |
27 | /**
28 | * @var string
29 | */
30 | protected $currentUser = null;
31 |
32 | /**
33 | * @param UserConfig[] $users
34 | */
35 | public function __construct(array $users = null)
36 | {
37 | if ($users) {
38 | foreach ($users as $name => $user) {
39 | if (!$user instanceof UserConfig) {
40 | throw new UnexpectedTypeException($user, 'Rollerworks\Bundle\MultiUserBundle\Model\UserConfig');
41 | }
42 |
43 | $this->users[$name] = $user;
44 | }
45 | }
46 | }
47 |
48 | /**
49 | * {@inheritdoc}
50 | */
51 | public function addUser($name, UserConfig $user)
52 | {
53 | $this->users[$name] = $user;
54 | }
55 |
56 | /**
57 | * {@inheritdoc}
58 | */
59 | public function getCurrentUserConfig()
60 | {
61 | if (!$this->currentUser) {
62 | throw new NoActiveUserSystemException('Unable to get UserConfig, because there is no user-system active. Please call setCurrentUser() to activate a user-system or refer to the user-system services directly.');
63 | }
64 |
65 | return $this->users[$this->currentUser];
66 | }
67 |
68 | /**
69 | * {@inheritdoc}
70 | */
71 | public function hasCurrentUserConfig()
72 | {
73 | return null !== $this->currentUser;
74 | }
75 |
76 | /**
77 | * {@inheritdoc}
78 | */
79 | public function setCurrentUser($name)
80 | {
81 | if (!isset($this->users[$name])) {
82 | throw new \LogicException(sprintf('Impossible to set the user discriminator, because "%s" is not present in the users list.', $name));
83 | }
84 |
85 | $this->currentUser = $name;
86 | }
87 |
88 | /**
89 | * {@inheritdoc}
90 | */
91 | public function getCurrentUser()
92 | {
93 | return $this->currentUser;
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/src/EventListener/AuthenticationListener.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\EventListener;
13 |
14 | use FOS\UserBundle\Event\UserEvent;
15 | use FOS\UserBundle\FOSUserEvents;
16 | use Rollerworks\Bundle\MultiUserBundle\Model\UserDiscriminatorInterface;
17 | use Symfony\Component\EventDispatcher\EventSubscriberInterface;
18 | use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
19 | use Symfony\Component\Security\Http\SecurityEvents;
20 |
21 | /**
22 | * Determines the current user-object by the authentication.
23 | *
24 | * @author Sebastiaan Stok
25 | */
26 | class AuthenticationListener implements EventSubscriberInterface
27 | {
28 | /**
29 | * @var UserDiscriminatorInterface
30 | */
31 | private $userDiscriminator;
32 |
33 | /**
34 | * @var string[]
35 | */
36 | private $users;
37 |
38 | /**
39 | * @param UserDiscriminatorInterface $userDiscriminator
40 | */
41 | public function __construct(UserDiscriminatorInterface $userDiscriminator)
42 | {
43 | $this->userDiscriminator = $userDiscriminator;
44 | }
45 |
46 | /**
47 | * @param string $name
48 | * @param string $class
49 | */
50 | public function addUser($name, $class)
51 | {
52 | $this->users[$class] = $name;
53 | }
54 |
55 | /**
56 | * @param UserEvent $event
57 | */
58 | public function onSecurityImplicitLogin(UserEvent $event)
59 | {
60 | $this->discriminate($event->getUser());
61 | }
62 |
63 | /**
64 | * @param InteractiveLoginEvent $event
65 | */
66 | public function onSecurityInteractiveLogin(InteractiveLoginEvent $event)
67 | {
68 | $this->discriminate($event->getAuthenticationToken()->getUser());
69 | }
70 |
71 | /**
72 | * @return array
73 | *
74 | * @codeCoverageIgnore
75 | */
76 | public static function getSubscribedEvents()
77 | {
78 | return array(
79 | FOSUserEvents::SECURITY_IMPLICIT_LOGIN => array('onSecurityImplicitLogin', 255),
80 | SecurityEvents::INTERACTIVE_LOGIN => array('onSecurityInteractiveLogin', 255),
81 | );
82 | }
83 |
84 | /**
85 | * @param $user
86 | */
87 | protected function discriminate($user)
88 | {
89 | $class = get_class($user);
90 | if (isset($this->users[$class])) {
91 | $this->userDiscriminator->setCurrentUser($this->users[$class]);
92 | }
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/src/EventListener/EmailConfirmationListener.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\EventListener;
13 |
14 | use FOS\UserBundle\Event\FormEvent;
15 | use FOS\UserBundle\FOSUserEvents;
16 | use FOS\UserBundle\Mailer\MailerInterface;
17 | use FOS\UserBundle\Util\TokenGeneratorInterface;
18 | use Rollerworks\Bundle\MultiUserBundle\Model\UserDiscriminatorInterface;
19 | use Symfony\Component\EventDispatcher\EventSubscriberInterface;
20 | use Symfony\Component\HttpFoundation\RedirectResponse;
21 | use Symfony\Component\HttpFoundation\Session\SessionInterface;
22 | use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
23 |
24 | class EmailConfirmationListener implements EventSubscriberInterface
25 | {
26 | private $mailer;
27 | private $tokenGenerator;
28 | private $router;
29 | private $session;
30 |
31 | /**
32 | * @var UserDiscriminatorInterface
33 | */
34 | private $userDiscriminator;
35 |
36 | public function __construct(MailerInterface $mailer, TokenGeneratorInterface $tokenGenerator, UrlGeneratorInterface $router, SessionInterface $session, UserDiscriminatorInterface $userDiscriminator)
37 | {
38 | $this->mailer = $mailer;
39 | $this->tokenGenerator = $tokenGenerator;
40 | $this->router = $router;
41 | $this->session = $session;
42 | $this->userDiscriminator = $userDiscriminator;
43 | }
44 |
45 | public static function getSubscribedEvents()
46 | {
47 | return array(
48 | FOSUserEvents::REGISTRATION_SUCCESS => 'onRegistrationSuccess',
49 | );
50 | }
51 |
52 | public function onRegistrationSuccess(FormEvent $event)
53 | {
54 | if (!$this->userDiscriminator->getCurrentUserConfig()->getConfig('registering.confirmation.enabled', false)) {
55 | return;
56 | }
57 |
58 | /** @var $user \FOS\UserBundle\Model\UserInterface */
59 | $user = $event->getForm()->getData();
60 |
61 | $user->setEnabled(false);
62 | if (null === $user->getConfirmationToken()) {
63 | $user->setConfirmationToken($this->tokenGenerator->generateToken());
64 | }
65 |
66 | $this->mailer->sendConfirmationEmailMessage($user);
67 | $this->session->set('fos_user_send_confirmation_email/email', $user->getEmail());
68 |
69 | $url = $this->router->generate($this->userDiscriminator->getCurrentUserConfig()->getRoutePrefix().'_registration_check_email');
70 | $event->setResponse(new RedirectResponse($url));
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/Controller/ResettingController.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\Controller;
13 |
14 | use FOS\UserBundle\Controller\ResettingController as BaseResettingController;
15 | use Symfony\Component\HttpFoundation\RedirectResponse;
16 | use Symfony\Component\HttpFoundation\Request;
17 |
18 | class ResettingController extends BaseResettingController
19 | {
20 | public function checkEmailAction(Request $request)
21 | {
22 | $userDiscriminator = $this->container->get('rollerworks_multi_user.user_discriminator');
23 | $email = $request->query->get('email');
24 |
25 | if (empty($email)) {
26 | // the user does not come from the sendEmail action
27 | return new RedirectResponse($this->container->get('router')->generate($userDiscriminator->getCurrentUserConfig()->getRoutePrefix().'_resetting_request'));
28 | }
29 |
30 | return $this->container->get('templating')->renderResponse('FOSUserBundle:Resetting:checkEmail.html.twig', array(
31 | 'email' => $email,
32 | ));
33 | }
34 |
35 | public function sendEmailAction(Request $request)
36 | {
37 | $userDiscriminator = $this->container->get('rollerworks_multi_user.user_discriminator');
38 | $username = $request->request->get('username');
39 | $user = $this->container->get('fos_user.user_manager')->findUserByUsernameOrEmail($username);
40 |
41 | if (null === $user) {
42 | return $this->container->get('templating')->renderResponse('FOSUserBundle:Resetting:request.html.twig', array('invalid_username' => $username));
43 | }
44 |
45 | if ($user->isPasswordRequestNonExpired($userDiscriminator->getCurrentUserConfig()->getConfig('resetting.token_ttl'))) {
46 | return $this->container->get('templating')->renderResponse('FOSUserBundle:Resetting:passwordAlreadyRequested.html.twig');
47 | }
48 |
49 | if (null === $user->getConfirmationToken()) {
50 | $tokenGenerator = $this->container->get('fos_user.util.token_generator');
51 | $user->setConfirmationToken($tokenGenerator->generateToken());
52 | }
53 |
54 | $this->container->get('fos_user.mailer')->sendResettingEmailMessage($user);
55 | $user->setPasswordRequestedAt(new \DateTime());
56 | $this->container->get('fos_user.user_manager')->updateUser($user);
57 |
58 | return new RedirectResponse($this->container->get('router')->generate(
59 | $userDiscriminator->getCurrentUserConfig()->getRoutePrefix().'_resetting_check_email',
60 | array('email' => $this->getObfuscatedEmail($user))
61 | ));
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/RollerworksMultiUserBundle.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle;
13 |
14 | use Rollerworks\Bundle\MultiUserBundle\DependencyInjection\Compiler\OverrideServiceCompilerPass;
15 | use Rollerworks\Bundle\MultiUserBundle\DependencyInjection\Compiler\RegisterUserPass;
16 | use Rollerworks\Bundle\MultiUserBundle\DependencyInjection\Compiler\RemoveParentServicesPass;
17 | use Symfony\Component\Console\Application;
18 | use Symfony\Component\DependencyInjection\ContainerBuilder;
19 | use Symfony\Component\Finder\Finder;
20 | use Symfony\Component\HttpKernel\Bundle\Bundle;
21 |
22 | /**
23 | * RollerworksMultiUserBundle.
24 | *
25 | * Provides user management functionality (authentication, authorization, etc).
26 | *
27 | * @author Sebastiaan Stok
28 | */
29 | class RollerworksMultiUserBundle extends Bundle
30 | {
31 | /**
32 | * {@inheritdoc}
33 | */
34 | public function build(ContainerBuilder $container)
35 | {
36 | parent::build($container);
37 |
38 | $container->addCompilerPass(new OverrideServiceCompilerPass());
39 | $container->addCompilerPass(new RemoveParentServicesPass());
40 | $container->addCompilerPass(new RegisterUserPass());
41 | }
42 |
43 | /**
44 | * {@inheritdoc}
45 | */
46 | public function getParent()
47 | {
48 | return 'FOSUserBundle';
49 | }
50 |
51 | /**
52 | * {@inheritdoc}
53 | */
54 | public function registerCommands(Application $application)
55 | {
56 | if (!is_dir($dir = $this->getPath().'/Command')) {
57 | return;
58 | }
59 |
60 | $finder = new Finder();
61 | $finder->files()->name('*Command.php')->in($dir);
62 |
63 | // Don't enable the generate command when SensioGeneratorBundle is not installed
64 | if (!class_exists('Sensio\\Bundle\\GeneratorBundle\\Command\\GenerateBundleCommand')) {
65 | $finder->notName('GenerateUserSysCommand.php');
66 | }
67 |
68 | $prefix = $this->getNamespace().'\\Command';
69 | foreach ($finder as $file) {
70 | $ns = $prefix;
71 | if ($relativePath = $file->getRelativePath()) {
72 | $ns .= '\\'.strtr($relativePath, '/', '\\');
73 | }
74 | $class = $ns.'\\'.$file->getBasename('.php');
75 |
76 | $r = new \ReflectionClass($class);
77 | if ($r->isSubclassOf('Symfony\\Component\\Console\\Command\\Command') && !$r->isAbstract() && !$r->getConstructor()->getNumberOfRequiredParameters()) {
78 | $application->add($r->newInstance());
79 | }
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/Resources/config/container/forms.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 | Rollerworks\Bundle\MultiUserBundle\Model\UserDiscriminator
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | registration
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | resetting
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | profile
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | change_password
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 | group
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/src/Model/DelegatingUserManager.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\Model;
13 |
14 | use FOS\UserBundle\Model\UserInterface;
15 | use FOS\UserBundle\Model\UserManagerInterface;
16 |
17 | /**
18 | * DelegatingUserManager selects a UserManager for the current user.
19 | *
20 | * Please don't use this manager as its only used for the original controllers.
21 | *
22 | * @author Sebastiaan Stok
23 | */
24 | class DelegatingUserManager implements UserManagerInterface
25 | {
26 | private $userDiscriminator;
27 |
28 | public function __construct(UserDiscriminatorInterface $userDiscriminator)
29 | {
30 | $this->userDiscriminator = $userDiscriminator;
31 | }
32 |
33 | /**
34 | * @return UserDiscriminatorInterface
35 | */
36 | public function getUserDiscriminator()
37 | {
38 | return $this->userDiscriminator;
39 | }
40 |
41 | public function createUser()
42 | {
43 | return $this->userDiscriminator->getCurrentUserConfig()->getUserManager()->createUser();
44 | }
45 |
46 | public function deleteUser(UserInterface $user)
47 | {
48 | $this->userDiscriminator->getCurrentUserConfig()->getUserManager()->deleteUser($user);
49 | }
50 |
51 | public function findUserBy(array $criteria)
52 | {
53 | return $this->userDiscriminator->getCurrentUserConfig()->getUserManager()->findUserBy($criteria);
54 | }
55 |
56 | public function findUserByUsername($username)
57 | {
58 | return $this->userDiscriminator->getCurrentUserConfig()->getUserManager()->findUserByUsername($username);
59 | }
60 |
61 | public function findUserByEmail($email)
62 | {
63 | return $this->userDiscriminator->getCurrentUserConfig()->getUserManager()->findUserByEmail($email);
64 | }
65 |
66 | public function findUserByUsernameOrEmail($usernameOrEmail)
67 | {
68 | return $this->userDiscriminator->getCurrentUserConfig()->getUserManager()->findUserByUsernameOrEmail($usernameOrEmail);
69 | }
70 |
71 | public function findUserByConfirmationToken($token)
72 | {
73 | return $this->userDiscriminator->getCurrentUserConfig()->getUserManager()->findUserByConfirmationToken($token);
74 | }
75 |
76 | public function findUsers()
77 | {
78 | return $this->userDiscriminator->getCurrentUserConfig()->getUserManager()->findUsers();
79 | }
80 |
81 | public function getClass()
82 | {
83 | return $this->userDiscriminator->getCurrentUserConfig()->getUserManager()->getClass();
84 | }
85 |
86 | public function reloadUser(UserInterface $user)
87 | {
88 | $this->userDiscriminator->getCurrentUserConfig()->getUserManager()->reloadUser($user);
89 | }
90 |
91 | public function updateUser(UserInterface $user)
92 | {
93 | $this->userDiscriminator->getCurrentUserConfig()->getUserManager()->updateUser($user);
94 | }
95 |
96 | public function updateCanonicalFields(UserInterface $user)
97 | {
98 | $this->userDiscriminator->getCurrentUserConfig()->getUserManager()->updateCanonicalFields($user);
99 | }
100 |
101 | public function updatePassword(UserInterface $user)
102 | {
103 | $this->userDiscriminator->getCurrentUserConfig()->getUserManager()->updatePassword($user);
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/src/DependencyInjection/Compiler/RegisterFosUserMappingsPass.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\DependencyInjection\Compiler;
13 |
14 | use Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass\RegisterMappingsPass;
15 | use Symfony\Component\DependencyInjection\Definition;
16 |
17 | class RegisterFosUserMappingsPass extends RegisterMappingsPass
18 | {
19 | public static function createOrmMappingDriver($servicePrefix)
20 | {
21 | $namespaces = self::getMappings();
22 |
23 | $arguments = array($namespaces, '.orm.xml');
24 | $locator = new Definition('Doctrine\Common\Persistence\Mapping\Driver\SymfonyFileLocator', $arguments);
25 | $driver = new Definition('Doctrine\ORM\Mapping\Driver\XmlDriver', array($locator));
26 |
27 | $managerParameters = array($servicePrefix.'.model_manager_name', 'doctrine.default_entity_manager');
28 | $enabledParameter = $servicePrefix.'.backend_type_orm';
29 |
30 | return new self(
31 | $driver,
32 | $namespaces,
33 | $managerParameters,
34 | 'doctrine.orm.%s_metadata_driver',
35 | $enabledParameter,
36 | 'doctrine.orm.%s_configuration'
37 | );
38 | }
39 |
40 | public static function createMongoDBMappingDriver($servicePrefix)
41 | {
42 | $namespaces = self::getMappings();
43 |
44 | $arguments = array($namespaces, '.mongodb.xml');
45 | $locator = new Definition('Doctrine\Common\Persistence\Mapping\Driver\SymfonyFileLocator', $arguments);
46 | $driver = new Definition('Doctrine\ODM\MongoDB\Mapping\Driver\XmlDriver', array($locator));
47 |
48 | $managerParameters = array($servicePrefix.'.model_manager_name', 'doctrine_mongodb.odm.default_document_manager');
49 | $enabledParameter = $servicePrefix.'.backend_type_mongodb';
50 |
51 | return new self(
52 | $driver,
53 | $namespaces,
54 | $managerParameters,
55 | 'doctrine_mongodb.odm.%s_metadata_driver',
56 | $enabledParameter,
57 | 'doctrine_mongodb.odm.%s_configuration'
58 | );
59 | }
60 |
61 | public static function createCouchDBMappingDriver($servicePrefix)
62 | {
63 | $namespaces = self::getMappings();
64 |
65 | $arguments = array($namespaces, '.couchdb.xml');
66 | $locator = new Definition('Doctrine\Common\Persistence\Mapping\Driver\SymfonyFileLocator', $arguments);
67 | $driver = new Definition('Doctrine\ODM\CouchDB\Mapping\Driver\XmlDriver', array($locator));
68 |
69 | $managerParameters = array($servicePrefix.'.model_manager_name', 'doctrine_couchdb.default_document_manager');
70 | $enabledParameter = $servicePrefix.'.backend_type_couchdb';
71 |
72 | return new self(
73 | $driver,
74 | $namespaces,
75 | $managerParameters,
76 | 'doctrine_couchdb.odm.%s_metadata_driver',
77 | $enabledParameter,
78 | 'doctrine_couchdb.odm.%s_configuration'
79 | );
80 | }
81 |
82 | private static function getMappings()
83 | {
84 | static $mappings;
85 |
86 | if (null === $mappings) {
87 | $r = new \ReflectionClass('FOS\UserBundle\FOSUserBundle');
88 | $mappings = array(
89 | realpath(dirname($r->getFilename()).'/Resources/config/doctrine-mapping') => 'FOS\UserBundle\Model',
90 | );
91 | }
92 |
93 | return $mappings;
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/src/DependencyInjection/RollerworksMultiUserExtension.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\DependencyInjection;
13 |
14 | use Symfony\Component\Config\FileLocator;
15 | use Symfony\Component\DependencyInjection\ContainerBuilder;
16 | use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
17 | use Symfony\Component\DependencyInjection\Loader;
18 | use Symfony\Component\HttpKernel\DependencyInjection\Extension;
19 |
20 | /**
21 | * @author Sebastiaan Stok
22 | */
23 | class RollerworksMultiUserExtension extends Extension implements PrependExtensionInterface
24 | {
25 | /**
26 | * {@inheritdoc}
27 | */
28 | public function load(array $configs, ContainerBuilder $container)
29 | {
30 | $configuration = new Configuration();
31 | $config = $this->processConfiguration($configuration, $configs);
32 |
33 | $loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
34 | $loader->load('container/services.xml');
35 | $loader->load('container/listeners.xml');
36 | $loader->load('container/forms.xml');
37 | $loader->load('container/templating_twig.xml');
38 | $loader->load('container/templating_php.xml');
39 |
40 | $container->setParameter('rollerworks_multi_user.from_email.address', $config['from_email']['address']);
41 | $container->setParameter('rollerworks_multi_user.from_email.sender_name', $config['from_email']['sender_name']);
42 |
43 | // add some required classes for compilation
44 | $this->addClassesToCompile(array(
45 | 'Rollerworks\\Bundle\\MultiUserBundle\\Model\\UserConfig',
46 | 'Rollerworks\\Bundle\\MultiUserBundle\\Model\\UserDiscriminator',
47 | 'Rollerworks\\Bundle\\MultiUserBundle\\EventListener\\RequestListener',
48 | 'Rollerworks\\Bundle\\MultiUserBundle\\EventListener\\AuthenticationListener',
49 | ));
50 | }
51 |
52 | public function prepend(ContainerBuilder $container)
53 | {
54 | $configs = $container->getExtensionConfig($this->getAlias());
55 | $config = $this->processConfiguration(new Configuration(), $configs);
56 |
57 | $fosConfig = array(
58 | 'db_driver' => $config['db_driver'], // Pass the driver until we have a proper fix for issue multiple drivers
59 | 'use_listener' => false,
60 | 'use_flash_notifications' => $config['use_flash_notifications'],
61 | 'firewall_name' => 'dummy',
62 | 'user_class' => 'Acme\UserBundle\Entity\User',
63 | 'from_email' => $config['from_email'],
64 | 'registration' => array(
65 | 'confirmation' => array(
66 | 'enabled' => false,
67 | ),
68 | ),
69 | 'service' => array(
70 | 'mailer' => 'rollerworks_multi_user.mailer.delegating',
71 | 'user_manager' => 'rollerworks_multi_user.user_manager.delegating',
72 | ),
73 | 'group' => array(
74 | 'group_class' => 'Acme\UserBundle\Entity\Group',
75 | 'group_manager' => 'rollerworks_multi_user.group_manager.delegating',
76 | ),
77 | );
78 |
79 | /*
80 | * We provide the FosUserBundle with a dummy configuration to load everything.
81 | * Later the parent services are removed.
82 | */
83 |
84 | $container->prependExtensionConfig('fos_user', $fosConfig);
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/Doctrine/AbstractUserListener.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\Doctrine;
13 |
14 | use Doctrine\Common\EventSubscriber;
15 | use Doctrine\Common\Persistence\Event\LifecycleEventArgs;
16 | use FOS\UserBundle\Model\UserInterface;
17 | use FOS\UserBundle\Model\UserManagerInterface;
18 | use Rollerworks\Bundle\MultiUserBundle\Model\UserDiscriminatorInterface;
19 | use Rollerworks\Component\SfContainerInjector\ContainerInjector;
20 |
21 | /**
22 | * Base Doctrine listener updating the canonical username and password fields.
23 | *
24 | * Overwritten by database specific listeners to register the right events and
25 | * to let the UoW recalculate the change set if needed.
26 | *
27 | * @author Sebastiaan Stok
28 | * @author Christophe Coevoet
29 | * @author David Buchmann
30 | */
31 | abstract class AbstractUserListener implements EventSubscriber
32 | {
33 | /**
34 | * @var UserManagerInterface
35 | */
36 | private $userManager;
37 |
38 | /**
39 | * @var UserDiscriminatorInterface
40 | */
41 | private $userDiscriminator;
42 |
43 | /**
44 | * @var ContainerInjector
45 | */
46 | private $container;
47 |
48 | /**
49 | * Constructor.
50 | *
51 | * @param ContainerInjector $container
52 | */
53 | public function __construct(ContainerInjector $container)
54 | {
55 | $this->container = $container;
56 | }
57 |
58 | /**
59 | * {inheritdoc}.
60 | */
61 | public function prePersist($args)
62 | {
63 | if (null === $this->userDiscriminator->getCurrentUser()) {
64 | return;
65 | }
66 |
67 | $object = $args->getObject();
68 | if ($object instanceof UserInterface && $this->userDiscriminator->getCurrentUserConfig()->getConfig('use_listener', true)) {
69 | $this->updateUserFields($object);
70 | }
71 | }
72 |
73 | /**
74 | * Pre update listener based on doctrine commons, overwrite to update
75 | * the changeset in the UoW and to handle non-common event argument
76 | * class.
77 | *
78 | * @param LifecycleEventArgs $args weak typed to allow overwriting
79 | */
80 | public function preUpdate($args)
81 | {
82 | if (null === $this->userDiscriminator->getCurrentUser()) {
83 | return;
84 | }
85 |
86 | $object = $args->getObject();
87 | if ($object instanceof UserInterface && $this->userDiscriminator->getCurrentUserConfig()->getConfig('use_listener', true)) {
88 | $this->updateUserFields($object);
89 | }
90 | }
91 |
92 | /**
93 | * This must be called on prePersist and preUpdate if the event is about a
94 | * user.
95 | *
96 | * @param UserInterface $user
97 | */
98 | protected function updateUserFields(UserInterface $user)
99 | {
100 | if (null === $this->userDiscriminator) {
101 | $this->userDiscriminator = $this->container->get('rollerworks_multi_user.user_discriminator');
102 | }
103 |
104 | // Can only use the user manager when there is an user-system active
105 | if (null === $this->userDiscriminator->getCurrentUser() || true !== $this->userDiscriminator->getCurrentUserConfig()->getConfig('use_listener', true)) {
106 | return;
107 | }
108 |
109 | if (null === $this->userManager) {
110 | $this->userManager = $this->container->get('fos_user.user_manager');
111 | }
112 |
113 | $this->userManager->updateCanonicalFields($user);
114 | $this->userManager->updatePassword($user);
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/src/Resources/config/container/listeners.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 | Symfony\Component\HttpFoundation\RequestMatcher
9 | Rollerworks\Bundle\MultiUserBundle\Model\UserDiscriminator
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/src/DependencyInjection/Compiler/RegisterUserPass.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\DependencyInjection\Compiler;
13 |
14 | use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
15 | use Symfony\Component\DependencyInjection\ContainerBuilder;
16 | use Symfony\Component\DependencyInjection\Reference;
17 |
18 | /**
19 | * RegisterUserPass, registers the user-systems with the UserDiscriminator.
20 | *
21 | * @author Sebastiaan Stok
22 | */
23 | class RegisterUserPass implements CompilerPassInterface
24 | {
25 | private $requestMatchers = array();
26 |
27 | /**
28 | * {@inheritdoc}
29 | */
30 | public function process(ContainerBuilder $container)
31 | {
32 | if (!$container->hasDefinition('rollerworks_multi_user.user_discriminator')) {
33 | return;
34 | }
35 |
36 | $requestListener = null;
37 | $authenticationListener = null;
38 |
39 | if ($container->hasDefinition('rollerworks_multi_user.listener.request')) {
40 | $requestListener = $container->getDefinition('rollerworks_multi_user.listener.request');
41 | }
42 |
43 | if ($container->hasDefinition('rollerworks_multi_user.listener.authentication')) {
44 | $authenticationListener = $container->getDefinition('rollerworks_multi_user.listener.authentication');
45 | }
46 |
47 | $userDiscriminator = $container->getDefinition('rollerworks_multi_user.user_discriminator');
48 |
49 | foreach ($container->findTaggedServiceIds('rollerworks_multi_user.user_system') as $id => $attributes) {
50 | $name = $attributes[0]['alias'];
51 |
52 | if (!isset($attributes[0]['request_matcher'])) {
53 | $requestMatcher = $this->createRequestMatcher($container, $container->getParameterBag()->resolveValue($attributes[0]['path']), $container->getParameterBag()->resolveValue($attributes[0]['host']));
54 | } else {
55 | $requestMatcher = new Reference($attributes[0]['request_matcher']);
56 | }
57 |
58 | if ($authenticationListener) {
59 | $authenticationListener->addMethodCall('addUser', array($name, $container->getParameterBag()->resolveValue($attributes[0]['class'])));
60 | }
61 |
62 | if ($requestListener) {
63 | $requestListener->addMethodCall('addUser', array($name, $requestMatcher));
64 | }
65 |
66 | $userDiscriminator->addMethodCall('addUser', array($name, new Reference($id)));
67 | }
68 | }
69 |
70 | /**
71 | * Copied from the SymfonySecurityBundle.
72 | */
73 | private function createRequestMatcher(ContainerBuilder $container, $path = null, $host = null, $methods = array(), $ip = null, array $attributes = array())
74 | {
75 | $serialized = serialize(array($path, $host, $methods, $ip, $attributes));
76 | $id = 'rollerworks_multi_user.request_matcher.'.md5($serialized).sha1($serialized);
77 |
78 | // Matcher already exist, which is not allowed
79 | if (isset($this->requestMatchers[$id])) {
80 | throw new \RuntimeException(sprintf(
81 | 'There is already a request-matcher for this configuration: path: "%s", host: "%s". Only one request matcher should match for the user system.',
82 | $path,
83 | $host
84 | ));
85 | }
86 |
87 | if ($methods) {
88 | $methods = array_map('strtoupper', (array) $methods);
89 | }
90 |
91 | // only add arguments that are necessary
92 | $arguments = array($path, $host, $methods, $ip, $attributes);
93 | while (count($arguments) > 0 && !end($arguments)) {
94 | array_pop($arguments);
95 | }
96 |
97 | $container
98 | ->register($id, '%rollerworks_multi_user.matcher.class%')
99 | ->setPublic(false)
100 | ->setArguments($arguments)
101 | ;
102 |
103 | return $this->requestMatchers[$id] = new Reference($id);
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | RollerworksMultiUserBundle
2 | ==========================
3 |
4 | # !! MAINTAINERS WANTED !!
5 |
6 | **This project is no longer actively maintained!**
7 | If you would like to takeover this project please leave a comment in:
8 | https://github.com/rollerworks/RollerworksMultiUserBundle/issues/96
9 |
10 | [](https://gitter.im/rollerworks/RollerworksMultiUserBundle?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
11 |
12 | [](https://travis-ci.org/rollerworks/RollerworksMultiUserBundle)
13 | [](https://scrutinizer-ci.com/g/rollerworks/RollerworksMultiUserBundle/)
14 | [](https://insight.sensiolabs.com/projects/9a47cef8-7640-4f20-9efe-0153325d66ba)
15 |
16 | The RollerworksMultiUserBundle adds support for a multi-user set-up using the FOSUserBundle.
17 | It provides a fully compatible in-place replacement for the 'fos_user' services.
18 |
19 | In practice it is build on-top of the FOSUserBundle, and uses the original controllers, forms and UserManager.
20 |
21 | Features include:
22 |
23 | - Fully compatible with existing bundles that already use the FOSUserBundle
24 | - Unlimited user-systems, each with there own configuration, storage engine, templates, forms, etc.
25 | - Easy generation of new user-systems
26 | - Unit tested
27 |
28 | **Caution:** This bundle is developed in sync with [FOSUserBundle's repository](https://github.com/FriendsOfSymfony/FOSUserBundle).
29 | For FOSUserBundle 2.0.x, you need to use the 1.0 release of the bundle (or lower).
30 |
31 | **As the FOSUserBundle 2.0 is not stable yet, multi-user support is considered experimental!**
32 |
33 | **Warning:** This bundle can not be used in combination with the PUGXMultiUserBundle.
34 | If the PUGXMultiUserBundle is installed, then please remove it before continuing.
35 |
36 | Documentation
37 | -------------
38 |
39 | The bulk of the documentation is stored in the `doc/index.md`
40 | file in this bundle:
41 |
42 | [Read the Documentation for master](https://github.com/rollerworks/RollerworksMultiUserBundle/blob/master/docs/index.md)
43 |
44 | Installation
45 | ------------
46 |
47 | All the installation instructions are located in [documentation](https://github.com/rollerworks/RollerworksMultiUserBundle/blob/master/docs/index.md).
48 |
49 | License
50 | -------
51 |
52 | This bundle is released under the MIT license.
53 | See the bundled LICENSE file for details.
54 |
55 | About
56 | -----
57 |
58 | RollerworksMultiUserBundle was designed as an alternative to the PUGXMultiUserBundle.
59 |
60 | A major difference to the PUGXMultiUserBundle is that RollerworksMultiUserBundle
61 | does not use Doctrine ORM Joined-Entity inheritance and provides a richer set of features.
62 |
63 | Reporting an issue or a feature request
64 | ---------------------------------------
65 |
66 | Issues and feature requests are tracked in the [Github issue tracker](https://github.com/Rollerworks/RollerworksMultiUserBundle/issues).
67 |
68 | When reporting a bug, it may be a good idea to reproduce it in a basic project
69 | built using the [Symfony Standard Edition](https://github.com/symfony/symfony-standard)
70 | to allow developers of the bundle to reproduce the issue by simply cloning it
71 | and following some steps.
72 |
73 | For opening a PR please use [Gush](http://gushphp.org/) so the information template is included.
74 |
75 | Credits
76 | -------
77 |
78 | The original idea of the UserDiscriminator came from the PUGXMultiUserBundle.
79 |
80 | A major difference to the PUGXMultiUserBundle is as that RollerworksMultiUserBundle
81 | does not use Doctrine ORM Joined-Entity inheritance and every user-manager is accessible without 'discriminating'.
82 |
83 | This bundle contains source originally designed by the FOSUserBundle developers.
84 |
85 | Running the Tests
86 | -------
87 |
88 | Before running the tests, you will need to install the bundle dependencies. Do this using composer:
89 |
90 | > The doctrine/mongodb-odm is required for functional tests
91 | > but are not installed by default as it fails with some of the automated code analyzers.
92 |
93 | ``` bash
94 | $ php composer.phar composer require doctrine/mongodb-odm:"1.0.*@dev" --no-update
95 | $ php composer.phar composer require doctrine/mongodb-odm-bundle:"3.0.*@dev" --no-update
96 | $ php composer.phar --dev install
97 | ```
98 |
99 | Then you can launch phpunit (make sure its installed https://github.com/sebastianbergmann/phpunit/#installation)
100 |
101 | > Using the Composer version of PHPUnit currently fails so make sure to either use the Phar archive or PEAR version.
102 | > You need at least version 3.6 of PHPUnit and MockObject plugin 1.0.8
103 |
104 | ``` bash
105 | $ phpunit -c phpunit.xml.dist
106 | ```
107 |
108 | **Note:** Functional test are not run by default, to run all tests make sure both
109 | PDO_SQLite and the PHP extension for MongoDB are installed, and launch phpunit with:
110 |
111 | ``` bash
112 | $ bin/phpunit -c phpunit.xml.dist --exclude-group ""
113 | ```
114 |
115 | > Optionally you may skip the functional tests as these are always run automatically on Travis-CI
116 | > when opening a Pull Request.
117 |
--------------------------------------------------------------------------------
/src/Model/UserConfig.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\Model;
13 |
14 | use FOS\UserBundle\Model\GroupManagerInterface;
15 | use FOS\UserBundle\Model\UserManagerInterface;
16 | use Rollerworks\Bundle\MultiUserBundle\Exception\MissingTemplateException;
17 |
18 | /**
19 | * UserConfiguration, holds the configuration of a user in the system.
20 | *
21 | * @author Sebastiaan Stok
22 | */
23 | class UserConfig
24 | {
25 | protected $servicePrefix;
26 | protected $routePrefix;
27 | protected $templates;
28 | protected $forms;
29 | protected $config;
30 |
31 | protected $userManager;
32 | protected $groupManager;
33 |
34 | /**
35 | * Constructor.
36 | *
37 | * @param string $servicePrefix
38 | * @param string $routePrefix
39 | * @param UserManagerInterface $userManager
40 | * @param GroupManagerInterface $groupManager
41 | */
42 | public function __construct($servicePrefix, $routePrefix, UserManagerInterface $userManager, GroupManagerInterface $groupManager)
43 | {
44 | $this->servicePrefix = $servicePrefix;
45 | $this->routePrefix = $routePrefix;
46 | $this->userManager = $userManager;
47 | $this->groupManager = $groupManager;
48 | $this->templates = array();
49 | $this->forms = array();
50 | $this->config = array();
51 | }
52 |
53 | /**
54 | * Set a config.
55 | *
56 | * @param string $name
57 | * @param string|int|bool|array $value
58 | */
59 | public function setConfig($name, $value)
60 | {
61 | $this->config[$name] = $value;
62 | }
63 |
64 | /**
65 | * @param string $name
66 | * @param string|int|bool|array $defaultValue
67 | *
68 | * @return string|int|bool|array
69 | */
70 | public function getConfig($name, $defaultValue = null)
71 | {
72 | return array_key_exists($name, $this->config) ? $this->config[$name] : $defaultValue;
73 | }
74 |
75 | /**
76 | * Set the form configuration.
77 | *
78 | * @param string $name
79 | * @param string $formName
80 | * @param string $type
81 | * @param array $validationGroups
82 | *
83 | * @return static
84 | */
85 | public function setForm($name, $formName, $type, array $validationGroups)
86 | {
87 | $this->forms[$name] = array('type' => $type, 'name' => $formName, 'validation_groups' => $validationGroups);
88 |
89 | return $this;
90 | }
91 |
92 | /**
93 | * Set the template configuration.
94 | *
95 | * @param string $name
96 | * @param string $resource
97 | *
98 | * @return static
99 | */
100 | public function setTemplate($name, $resource)
101 | {
102 | $this->templates[$name] = $resource;
103 |
104 | return $this;
105 | }
106 |
107 | /**
108 | * Get the form-type name for the given config-name.
109 | *
110 | * @param string $name
111 | *
112 | * @return string|null
113 | */
114 | public function getFormType($name)
115 | {
116 | return isset($this->forms[$name]['type']) ? $this->forms[$name]['type'] : null;
117 | }
118 |
119 | /**
120 | * Get the form name for the given config-name.
121 | *
122 | * @param string $name
123 | *
124 | * @return string|null
125 | */
126 | public function getFormName($name)
127 | {
128 | return isset($this->forms[$name]['name']) ? $this->forms[$name]['name'] : null;
129 | }
130 |
131 | /**
132 | * Get the validation groups for the given config-name.
133 | *
134 | * @param string $name
135 | *
136 | * @return array|null
137 | */
138 | public function getFormValidationGroups($name)
139 | {
140 | return isset($this->forms[$name]['validation_groups']) ? $this->forms[$name]['validation_groups'] : null;
141 | }
142 |
143 | /**
144 | * Get the View template for the given config-name.
145 | *
146 | * @param string $name
147 | *
148 | * @return string
149 | */
150 | public function getTemplate($name)
151 | {
152 | if (!isset($this->templates[$name])) {
153 | throw new MissingTemplateException(sprintf('Unable to get template for "%s", there is no such template configured.', $name));
154 | }
155 |
156 | $template = (string) $this->templates[$name];
157 | if ('' === $template) {
158 | throw new MissingTemplateException(sprintf('Unable to get template for "%s", it seems the template value is empty. Make sure you enabled the proper section and configured a proper value.', $name));
159 | }
160 |
161 | return $template;
162 | }
163 |
164 | /**
165 | * @return UserManagerInterface
166 | */
167 | public function getUserManager()
168 | {
169 | return $this->userManager;
170 | }
171 |
172 | /**
173 | * @return GroupManagerInterface
174 | */
175 | public function getGroupManager()
176 | {
177 | return $this->groupManager;
178 | }
179 |
180 | /**
181 | * @return string
182 | */
183 | public function getServicePrefix()
184 | {
185 | return $this->servicePrefix;
186 | }
187 |
188 | /**
189 | * @return string
190 | */
191 | public function getRoutePrefix()
192 | {
193 | return $this->routePrefix;
194 | }
195 | }
196 |
--------------------------------------------------------------------------------
/docs/overriding_templates.md:
--------------------------------------------------------------------------------
1 | Overriding Default RollerworksMultiUserBundle Templates
2 | =======================================================
3 |
4 | **Tip:** Each UserBundle can have it's own templates, the technique
5 | described in this section is only meant for when you want to "keep things simple".
6 |
7 | As you start to incorporate RollerworksMultiUserBundle into your application,
8 | you will probably find that you need to override the default templates that are
9 | provided by the bundle. Although the template names are not configurable, the Symfony2
10 | framework provides two ways to override the templates of a bundle.
11 |
12 | > Because of the Bundle inheritance you should only overwrite the
13 | > RollerworksMultiUserBundle (not the FOSUserBundle) in your `app/Resources`.
14 |
15 | 1. Define a new template of the same name in the `app/Resources` directory
16 | 2. Create a new bundle that is defined as a child of `RollerworksMultiUserBundle`
17 |
18 | **Caution:**
19 |
20 | Unlike the FOSUserBundle template files (except `layout.html.twig`)
21 | should be placed inside `views/UserBundle` (instead of directly
22 | in the `views` folder).
23 |
24 | Failing to do so will break the automatic loading of the configured template.
25 |
26 | ### Example: Overriding The Default layout.html.twig
27 |
28 | It is highly recommended that you override the `Resources/views/layout.html.twig`
29 | template so that the pages provided by the RollerworksMultiUserBundle have a similar look and
30 | feel to the rest of your application. An example of overriding this layout template
31 | is demonstrated below using both of the overriding options listed above.
32 |
33 | Here is the default `layout.html.twig` provided by the RollerworksMultiUserBundle:
34 |
35 | ``` html+jinja
36 |
37 |
38 |
39 |
40 |
41 |
42 |
52 |
53 | {% for type, messages in app.session.flashbag.all() %}
54 | {% for key, message in messages %}
55 |
56 | {{ message|trans({}, 'FOSUserBundle') }}
57 |
58 | {% endfor %}
59 | {% endfor %}
60 |
61 |
62 | {% block fos_user_content %}
63 | {% endblock fos_user_content %}
64 |
65 |
66 |
67 | ```
68 |
69 | As you can see its pretty basic and doesn't really have much structure, so you will
70 | want to replace it with a layout file that is appropriate for your application. The
71 | main thing to note in this template is the block named `fos_user_content`. This is
72 | the block where the content from each of the different bundle's actions will be
73 | displayed, so you must make sure to include this block in the layout file you will
74 | use to override the default one.
75 |
76 | > The `{{ path(rollerworks_multi_user_user().getRoutePrefix() ~ '_security_login') }}` will generate the `_security_login`
77 | > route for the active user-system. If you want your 'own' templates to support multiple user-systems,
78 | > this the recommended way to generate routes for your user-systems.
79 |
80 | The following Twig template file is an example of a layout file that might be used
81 | to override the one provided by the bundle.
82 |
83 | ``` html+jinja
84 | {% extends 'AcmeDemoBundle::layout.html.twig' %}
85 |
86 | {% block title %}Acme Demo Application{% endblock %}
87 |
88 | {% block content %}
89 | {% block fos_user_content %}{% endblock %}
90 | {% endblock %}
91 | ```
92 |
93 | This example extends the layout template from a fictional application bundle named
94 | `AcmeDemoBundle`. The `content` block is where the main content of each page is rendered.
95 | This is why the `fos_user_content` block has been placed inside of it. This will
96 | lead to the desired effect of having the output from the RollerworksMultiUserBundle actions
97 | integrated into our applications layout, preserving the look and feel of the
98 | application.
99 |
100 | **a) Define New Template In app/Resources**
101 |
102 | The easiest way to override a bundle's template is to simply place a new one in
103 | your `app/Resources` folder. To override the layout template located at
104 | `Resources/views/layout.html.twig` in the `RollerworksMultiUserBundle` directory, you would place
105 | your new layout template at `app/Resources/RollerworksMultiUserBundle/views/layout.html.twig`.
106 |
107 | As you can see the pattern for overriding templates in this way is to
108 | create a folder with the name of the bundle class in the `app/Resources` directory.
109 | Then add your new template to this folder, preserving the directory structure from the
110 | original bundle.
111 |
112 | **b) Create A Child Bundle And Override Template**
113 |
114 | **Note:**
115 |
116 | ```
117 | This method is more complicated than the one outlined above. Unless you are
118 | planning to override the controllers as well as the templates, it is recommended
119 | that you use the other method.
120 | ```
121 |
122 | As listed above, you can also create a bundle defined as child of RollerworksMultiUserBundle
123 | and place the new template in the same location that is resides in the RollerworksMultiUserBundle.
124 | The first thing you want to do is override the `getParent` method to your bundle
125 | class.
126 |
127 | ``` php
128 | // src/Acme/UserBundle/AcmeUserBundle.php
129 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\EventListener;
13 |
14 | use FOS\UserBundle\FOSUserEvents;
15 | use Rollerworks\Bundle\MultiUserBundle\Model\UserDiscriminatorInterface;
16 | use Symfony\Component\EventDispatcher\Event;
17 | use Symfony\Component\EventDispatcher\EventDispatcherInterface;
18 | use Symfony\Component\EventDispatcher\EventSubscriberInterface;
19 |
20 | /**
21 | * @author Sebastiaan Stok
22 | */
23 | class EventDiscriminator implements EventSubscriberInterface
24 | {
25 | /**
26 | * @var UserDiscriminatorInterface
27 | */
28 | private $userDiscriminator;
29 |
30 | /**
31 | * @var EventDispatcherInterface
32 | */
33 | private $eventDispatcher;
34 |
35 | /**
36 | * @param UserDiscriminatorInterface $userDiscriminator
37 | * @param EventDispatcherInterface $eventDispatcher
38 | */
39 | public function __construct(UserDiscriminatorInterface $userDiscriminator, EventDispatcherInterface $eventDispatcher)
40 | {
41 | $this->userDiscriminator = $userDiscriminator;
42 | $this->eventDispatcher = $eventDispatcher;
43 | }
44 |
45 | // dispatchers and event-subscriber list is generated using scripts/generate-events.php
46 | // last updated on 2014-03-06
47 |
48 | public function dispatchChangePasswordInitialize(Event $e)
49 | {
50 | if ($userSys = $this->userDiscriminator->getCurrentUser()) {
51 | $this->eventDispatcher->dispatch($userSys.'.change_password.edit.initialize', $e);
52 | }
53 | }
54 |
55 | public function dispatchChangePasswordSuccess(Event $e)
56 | {
57 | if ($userSys = $this->userDiscriminator->getCurrentUser()) {
58 | $this->eventDispatcher->dispatch($userSys.'.change_password.edit.success', $e);
59 | }
60 | }
61 |
62 | public function dispatchChangePasswordCompleted(Event $e)
63 | {
64 | if ($userSys = $this->userDiscriminator->getCurrentUser()) {
65 | $this->eventDispatcher->dispatch($userSys.'.change_password.edit.completed', $e);
66 | }
67 | }
68 |
69 | public function dispatchGroupCreateInitialize(Event $e)
70 | {
71 | if ($userSys = $this->userDiscriminator->getCurrentUser()) {
72 | $this->eventDispatcher->dispatch($userSys.'.group.create.initialize', $e);
73 | }
74 | }
75 |
76 | public function dispatchGroupCreateSuccess(Event $e)
77 | {
78 | if ($userSys = $this->userDiscriminator->getCurrentUser()) {
79 | $this->eventDispatcher->dispatch($userSys.'.group.create.success', $e);
80 | }
81 | }
82 |
83 | public function dispatchGroupCreateCompleted(Event $e)
84 | {
85 | if ($userSys = $this->userDiscriminator->getCurrentUser()) {
86 | $this->eventDispatcher->dispatch($userSys.'.group.create.completed', $e);
87 | }
88 | }
89 |
90 | public function dispatchGroupDeleteCompleted(Event $e)
91 | {
92 | if ($userSys = $this->userDiscriminator->getCurrentUser()) {
93 | $this->eventDispatcher->dispatch($userSys.'.group.delete.completed', $e);
94 | }
95 | }
96 |
97 | public function dispatchGroupEditInitialize(Event $e)
98 | {
99 | if ($userSys = $this->userDiscriminator->getCurrentUser()) {
100 | $this->eventDispatcher->dispatch($userSys.'.group.edit.initialize', $e);
101 | }
102 | }
103 |
104 | public function dispatchGroupEditSuccess(Event $e)
105 | {
106 | if ($userSys = $this->userDiscriminator->getCurrentUser()) {
107 | $this->eventDispatcher->dispatch($userSys.'.group.edit.success', $e);
108 | }
109 | }
110 |
111 | public function dispatchGroupEditCompleted(Event $e)
112 | {
113 | if ($userSys = $this->userDiscriminator->getCurrentUser()) {
114 | $this->eventDispatcher->dispatch($userSys.'.group.edit.completed', $e);
115 | }
116 | }
117 |
118 | public function dispatchProfileEditInitialize(Event $e)
119 | {
120 | if ($userSys = $this->userDiscriminator->getCurrentUser()) {
121 | $this->eventDispatcher->dispatch($userSys.'.profile.edit.initialize', $e);
122 | }
123 | }
124 |
125 | public function dispatchProfileEditSuccess(Event $e)
126 | {
127 | if ($userSys = $this->userDiscriminator->getCurrentUser()) {
128 | $this->eventDispatcher->dispatch($userSys.'.profile.edit.success', $e);
129 | }
130 | }
131 |
132 | public function dispatchProfileEditCompleted(Event $e)
133 | {
134 | if ($userSys = $this->userDiscriminator->getCurrentUser()) {
135 | $this->eventDispatcher->dispatch($userSys.'.profile.edit.completed', $e);
136 | }
137 | }
138 |
139 | public function dispatchRegistrationInitialize(Event $e)
140 | {
141 | if ($userSys = $this->userDiscriminator->getCurrentUser()) {
142 | $this->eventDispatcher->dispatch($userSys.'.registration.initialize', $e);
143 | }
144 | }
145 |
146 | public function dispatchRegistrationSuccess(Event $e)
147 | {
148 | if ($userSys = $this->userDiscriminator->getCurrentUser()) {
149 | $this->eventDispatcher->dispatch($userSys.'.registration.success', $e);
150 | }
151 | }
152 |
153 | public function dispatchRegistrationCompleted(Event $e)
154 | {
155 | if ($userSys = $this->userDiscriminator->getCurrentUser()) {
156 | $this->eventDispatcher->dispatch($userSys.'.registration.completed', $e);
157 | }
158 | }
159 |
160 | public function dispatchRegistrationConfirm(Event $e)
161 | {
162 | if ($userSys = $this->userDiscriminator->getCurrentUser()) {
163 | $this->eventDispatcher->dispatch($userSys.'.registration.confirm', $e);
164 | }
165 | }
166 |
167 | public function dispatchRegistrationConfirmed(Event $e)
168 | {
169 | if ($userSys = $this->userDiscriminator->getCurrentUser()) {
170 | $this->eventDispatcher->dispatch($userSys.'.registration.confirmed', $e);
171 | }
172 | }
173 |
174 | public function dispatchResettingResetInitialize(Event $e)
175 | {
176 | if ($userSys = $this->userDiscriminator->getCurrentUser()) {
177 | $this->eventDispatcher->dispatch($userSys.'.resetting.reset.initialize', $e);
178 | }
179 | }
180 |
181 | public function dispatchResettingResetSuccess(Event $e)
182 | {
183 | if ($userSys = $this->userDiscriminator->getCurrentUser()) {
184 | $this->eventDispatcher->dispatch($userSys.'.resetting.reset.success', $e);
185 | }
186 | }
187 |
188 | public function dispatchResettingResetCompleted(Event $e)
189 | {
190 | if ($userSys = $this->userDiscriminator->getCurrentUser()) {
191 | $this->eventDispatcher->dispatch($userSys.'.resetting.reset.completed', $e);
192 | }
193 | }
194 |
195 | public function dispatchSecurityImplicitLogin(Event $e)
196 | {
197 | if ($userSys = $this->userDiscriminator->getCurrentUser()) {
198 | $this->eventDispatcher->dispatch($userSys.'.security.implicit_login', $e);
199 | }
200 | }
201 |
202 | /**
203 | * Subscribes to all events defined in FOS\UserBundle\FOSUserEvents.
204 | *
205 | * @return array
206 | */
207 | public static function getSubscribedEvents()
208 | {
209 | return array(
210 | FOSUserEvents::CHANGE_PASSWORD_INITIALIZE => 'dispatchChangePasswordInitialize',
211 | FOSUserEvents::CHANGE_PASSWORD_SUCCESS => 'dispatchChangePasswordSuccess',
212 | FOSUserEvents::CHANGE_PASSWORD_COMPLETED => 'dispatchChangePasswordCompleted',
213 | FOSUserEvents::GROUP_CREATE_INITIALIZE => 'dispatchGroupCreateInitialize',
214 | FOSUserEvents::GROUP_CREATE_SUCCESS => 'dispatchGroupCreateSuccess',
215 | FOSUserEvents::GROUP_CREATE_COMPLETED => 'dispatchGroupCreateCompleted',
216 | FOSUserEvents::GROUP_DELETE_COMPLETED => 'dispatchGroupDeleteCompleted',
217 | FOSUserEvents::GROUP_EDIT_INITIALIZE => 'dispatchGroupEditInitialize',
218 | FOSUserEvents::GROUP_EDIT_SUCCESS => 'dispatchGroupEditSuccess',
219 | FOSUserEvents::GROUP_EDIT_COMPLETED => 'dispatchGroupEditCompleted',
220 | FOSUserEvents::PROFILE_EDIT_INITIALIZE => 'dispatchProfileEditInitialize',
221 | FOSUserEvents::PROFILE_EDIT_SUCCESS => 'dispatchProfileEditSuccess',
222 | FOSUserEvents::PROFILE_EDIT_COMPLETED => 'dispatchProfileEditCompleted',
223 | FOSUserEvents::REGISTRATION_INITIALIZE => 'dispatchRegistrationInitialize',
224 | FOSUserEvents::REGISTRATION_SUCCESS => 'dispatchRegistrationSuccess',
225 | FOSUserEvents::REGISTRATION_COMPLETED => 'dispatchRegistrationCompleted',
226 | FOSUserEvents::REGISTRATION_CONFIRM => 'dispatchRegistrationConfirm',
227 | FOSUserEvents::REGISTRATION_CONFIRMED => 'dispatchRegistrationConfirmed',
228 | FOSUserEvents::RESETTING_RESET_INITIALIZE => 'dispatchResettingResetInitialize',
229 | FOSUserEvents::RESETTING_RESET_SUCCESS => 'dispatchResettingResetSuccess',
230 | FOSUserEvents::RESETTING_RESET_COMPLETED => 'dispatchResettingResetCompleted',
231 | FOSUserEvents::SECURITY_IMPLICIT_LOGIN => 'dispatchSecurityImplicitLogin',
232 | );
233 | }
234 | }
235 |
--------------------------------------------------------------------------------
/src/Resources/skeleton/bundle/Extension.php.twig:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace {{
13 |
14 | namespace }}\DependencyInjection;
15 |
16 | { % block use_statements % }
17 | use Rollerworks\Bundle\MultiUserBundle\DependencyInjection\Factory\UserServicesFactory;
18 | use Symfony\Component\Config\FileLocator;
19 | use Symfony\Component\DependencyInjection\ContainerBuilder;
20 | use Symfony\Component\DependencyInjection\Loader;
21 | use Symfony\Component\HttpKernel\DependencyInjection\Extension;
22 |
23 | { % endblock use_statements % }
24 |
25 | /*
26 | {% block phpdoc_class_header %}
27 | * This is the class that loads and manages your bundle configuration
28 | {% endblock phpdoc_class_header %}
29 | *
30 | * To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html}
31 | */
32 | { % block class_definition % }
33 | class
34 | {
35 | { bundle_basename }
36 | }Extension extends Extension
37 | { % endblock class_definition % }
38 | {
39 | { % block class_body % }
40 | /**
41 | * {@inheritdoc}
42 | */
43 | public function load(array $configs, ContainerBuilder $container)
44 | {
45 | $configuration = new Configuration();
46 | $config = $this->processConfiguration($configuration, $configs);
47 |
48 | $factory = new UserServicesFactory($container);
49 |
50 | // The first parameter is the name of the user-system, the second is the configuration which internally
51 | // is normalized by the Symfony Config component.
52 |
53 | /*
54 | The `UserServicesFactory::create()` will also register the form-types you need,
55 | any form-type/name/class that belongs to the FOSUserBundle will be converted to an ready
56 | to use form-type. Remember form types and names start with the service-prefix of the user-system.
57 |
58 | ```
59 | 'form' => array(
60 | 'type' => 'fos_user_profile',
61 | 'class' => 'FOS\UserBundle\Form\Type\ProfileFormType',
62 | 'name' => 'fos_user_profile_form',
63 | ),
64 | ```
65 |
66 | Will internally get converted to an '{{ extension_alias }}_profile' form-type service definition.
67 | Never set the template namespace to FOSUserBundle or RollerworksMultiUserBundle as this will create an endless recursion!
68 | */
69 |
70 | $factory->create('{{ extension_alias }}', array(
71 | array(
72 | /*
73 | * `path` and `host` are used by the `RequestListener` service for finding the correct user-type.
74 | * You can either set only a path or host, or both. Or you can choose to use your own matcher-service
75 | * by setting the `request_matcher`, and giving it the service-id.
76 | *
77 | * A request-matcher must always implement the `Symfony\Component\HttpFoundation\RequestMatcherInterface`.
78 | */
79 |
80 | 'path' => '^/', // path-regex, must match the firewall pattern
81 | 'host' => null,
82 | 'request_matcher' => null,
83 |
84 | // When not set this will inherit from the user-system name provided above
85 | 'services_prefix' => '{{ extension_alias }}',
86 | 'routes_prefix' => '{{ extension_alias }}',
87 |
88 | 'db_driver' => '{{ db_driver }}', // can be either: orm, mongodb, couchdb or custom (Propel is not supported)
89 | 'model_manager_name' => 'default',
90 | 'use_listener' => true,
91 |
92 | 'user_class' => '{{ model_namespace }}\User',
93 | 'firewall_name' => 'main', // this must equal to the firewall-name used for this user-system
94 |
95 | 'use_username_form_type' => true,
96 |
97 | // When not set these will inherit from the system wide configuration
98 | 'from_email' => array(
99 | 'address' => null,
100 | 'sender_name' => null,
101 | ),
102 |
103 | 'security' => array(
104 | 'login' => array(
105 | 'template' => 'RollerworksMultiUserBundle:UserBundle/Security:login.html.twig',
106 | ),
107 | ),
108 |
109 | 'service' => array(
110 | 'mailer' => 'fos_user.mailer.default',
111 | 'email_canonicalizer' => 'fos_user.util.canonicalizer.default',
112 | 'username_canonicalizer' => 'fos_user.util.canonicalizer.default',
113 | 'user_manager' => 'fos_user.user_manager.default',
114 | ),
115 |
116 | 'template' => array(
117 | 'layout' => 'RollerworksMultiUserBundle::layout.html.twig',
118 | ),
119 |
120 | 'profile' => array(
121 | 'form' => array(
122 | 'class' => 'FOS\\UserBundle\\Form\\Type\\ProfileFormType',
123 | 'type' => 'fos_user_profile',
124 | 'name' => 'fos_user_profile_form',
125 | 'validation_groups' => array('Profile', 'Default'),
126 | ),
127 | 'template' => array(
128 | 'edit' => 'RollerworksMultiUserBundle:UserBundle/Profile:edit.html.twig',
129 | 'show' => 'RollerworksMultiUserBundle:UserBundle/Profile:show.html.twig',
130 | ),
131 | ),
132 |
133 | 'change_password' => array(
134 | 'form' => array(
135 | 'class' => 'FOS\\UserBundle\\Form\\Type\\ChangePasswordFormType',
136 | 'type' => 'fos_user_change_password',
137 | 'name' => 'fos_user_change_password_form',
138 | 'validation_groups' => array('ChangePassword', 'Default'),
139 | ),
140 | 'template' => array(
141 | 'change_password' => 'RollerworksMultiUserBundle:UserBundle/ChangePassword:changePassword.html.twig',
142 | ),
143 | ),
144 |
145 | 'registration' => array(
146 | 'confirmation' => array(
147 | 'enabled' => false,
148 | 'template' => array(
149 | 'email' => 'RollerworksMultiUserBundle:UserBundle/Registration:email.txt.twig',
150 | 'confirmed' => 'RollerworksMultiUserBundle:UserBundle/Registration:confirmed.html.twig',
151 | ),
152 | 'from_email' => array(
153 | 'address' => null,
154 | 'sender_name' => null,
155 | ),
156 | ),
157 | 'form' => array(
158 | 'class' => 'FOS\\UserBundle\\Form\\Type\\RegistrationFormType',
159 | 'type' => 'fos_user_registration',
160 | 'name' => 'fos_user_registration_form',
161 | 'validation_groups' => array('Registration', 'Default'),
162 | ),
163 | 'template' => array(
164 | 'register' => 'RollerworksMultiUserBundle:UserBundle/Registration:register.html.twig',
165 | 'check_email' => 'RollerworksMultiUserBundle:UserBundle/Registration:checkEmail.html.twig',
166 | ),
167 | ),
168 |
169 | 'resetting' => array(
170 | 'token_ttl' => 86400,
171 | 'email' => array(
172 | 'from_email' => array(
173 | 'address' => null,
174 | 'sender_name' => null,
175 | ),
176 | ),
177 | 'form' => array(
178 | 'template' => null,
179 | 'class' => 'FOS\\UserBundle\\Form\\Type\\ResettingFormType',
180 | 'type' => 'fos_user_resetting',
181 | 'name' => 'fos_user_resetting_form',
182 | 'validation_groups' => array('ResetPassword', 'Default'),
183 | ),
184 | 'template' => array(
185 | 'check_email' => 'RollerworksMultiUserBundle:UserBundle/Resetting:checkEmail.html.twig',
186 | 'email' => 'RollerworksMultiUserBundle:UserBundle/Resetting:email.txt.twig',
187 | 'password_already_requested' => 'RollerworksMultiUserBundle:UserBundle/Resetting:passwordAlreadyRequested.html.twig',
188 | 'request' => 'RollerworksMultiUserBundle:UserBundle/Resetting:request.html.twig',
189 | 'reset' => 'RollerworksMultiUserBundle:UserBundle/Resetting:reset.html.twig',
190 | ),
191 | ),
192 |
193 | // Optional
194 | /*
195 | 'group' => array(
196 | 'group_class' => '{{ model_namespace }}\Group',
197 | 'group_manager' => 'fos_user.group_manager.default',
198 |
199 | 'form' => array(
200 | 'class' => 'FOS\\UserBundle\\Form\\Type\\GroupFormType',
201 | 'type' => 'fos_user_group',
202 | 'name' => 'fos_user_group_form',
203 | 'validation_groups' => array('Registration', 'Default'),
204 | ),
205 | 'template' => array(
206 | 'edit' => 'RollerworksMultiUserBundle:UserBundle/Group:edit.html.twig',
207 | 'list' => 'RollerworksMultiUserBundle:UserBundle/Group:list.html.twig',
208 | 'new' => 'RollerworksMultiUserBundle:UserBundle/Group:new.html.twig',
209 | 'show' => 'RollerworksMultiUserBundle:UserBundle/Group:show.html.twig',
210 | ),
211 | ),
212 | */
213 | ),
214 | $config,
215 | ));
216 |
217 | { % if {
218 | format == 'yml' - %
219 | }
220 | $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); }
221 | $loader->load('services.yml');
222 | { % - elseif {
223 | format == 'xml' - %
224 | }
225 | $loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); }
226 | $loader->load('services.xml');
227 | { % - elseif {
228 | format == 'php' - %
229 | }
230 | $loader = new Loader\PhpFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); }
231 | $loader->load('services.php');
232 | { % -endif % }
233 | }
234 | { % endblock class_body % }
235 | }
236 |
--------------------------------------------------------------------------------
/src/Generator/UserBundleGenerator.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\Generator;
13 |
14 | use Sensio\Bundle\GeneratorBundle\Generator\Generator;
15 | use Symfony\Component\DependencyInjection\Container;
16 | use Symfony\Component\Filesystem\Filesystem;
17 |
18 | /**
19 | * Generates a bundle.
20 | *
21 | * @author Sebastiaan Stok
22 | * @author Fabien Potencier
23 | */
24 | class UserBundleGenerator extends Generator
25 | {
26 | private $filesystem;
27 |
28 | public function __construct(Filesystem $filesystem)
29 | {
30 | $this->filesystem = $filesystem;
31 | }
32 |
33 | /**
34 | * @param string $namespace
35 | * @param string $bundle
36 | * @param string $dir
37 | * @param string $format
38 | * @param string $structure
39 | * @param string $dbDriver
40 | *
41 | * @throws \RuntimeException
42 | */
43 | public function generate($namespace, $bundle, $dir, $format, $structure, $dbDriver)
44 | {
45 | $dir .= '/'.strtr($namespace, '\\', '/');
46 | if (file_exists($dir)) {
47 | if (!is_dir($dir)) {
48 | throw new \RuntimeException(sprintf('Unable to generate the bundle as the target directory "%s" exists but is a file.', realpath($dir)));
49 | }
50 | $files = scandir($dir);
51 | if ($files != array('.', '..')) {
52 | throw new \RuntimeException(sprintf('Unable to generate the bundle as the target directory "%s" is not empty.', realpath($dir)));
53 | }
54 | if (!is_writable($dir)) {
55 | throw new \RuntimeException(sprintf('Unable to generate the bundle as the target directory "%s" is not writable.', realpath($dir)));
56 | }
57 | }
58 |
59 | $driverDir = array(
60 | 'orm' => 'Entity',
61 | 'mongodb' => 'Document',
62 | 'couchdb' => 'CouchDocument',
63 | 'custom' => 'Model',
64 | );
65 |
66 | $basename = substr($bundle, 0, -6);
67 | $parameters = array(
68 | 'namespace' => $namespace,
69 | 'bundle' => $bundle,
70 | 'format' => $format,
71 | 'db_driver' => $dbDriver,
72 | 'model_namespace' => $namespace.'\\'.$driverDir[$dbDriver],
73 | 'bundle_basename' => $basename,
74 | 'extension_alias' => Container::underscore($basename),
75 | );
76 |
77 | $this->renderFile('bundle/Bundle.php.twig', $dir.'/'.$bundle.'.php', $parameters);
78 | $this->renderFile('bundle/Extension.php.twig', $dir.'/DependencyInjection/'.$basename.'Extension.php', $parameters);
79 | $this->renderFile('bundle/Configuration.php.twig', $dir.'/DependencyInjection/Configuration.php', $parameters);
80 | $this->renderFile('bundle/DefaultController.php.twig', $dir.'/Controller/DefaultController.php', $parameters);
81 | $this->renderFile('bundle/DefaultControllerTest.php.twig', $dir.'/Tests/Controller/DefaultControllerTest.php', $parameters);
82 | $this->renderFile('bundle/index.html.twig.twig', $dir.'/Resources/views/Default/index.html.twig', $parameters);
83 | $this->renderFile('bundle/services.'.$format.'.twig', $dir.'/Resources/config/services.'.$format, $parameters);
84 |
85 | $this->generateRoutes($namespace, $bundle, $dir, $format, $basename);
86 | $this->generateModels($namespace, $bundle, $dir, $dbDriver, $basename);
87 | $this->generateEventsClass($namespace, $bundle, $dir, $dbDriver, $basename);
88 |
89 | if ($structure) {
90 | $this->renderFile('bundle/messages.fr.xlf', $dir.'/Resources/translations/messages.fr.xlf', $parameters);
91 |
92 | $this->filesystem->mkdir($dir.'/Resources/doc');
93 | $this->filesystem->touch($dir.'/Resources/doc/index.rst');
94 | $this->filesystem->mkdir($dir.'/Resources/translations');
95 | $this->filesystem->mkdir($dir.'/Resources/public/css');
96 | $this->filesystem->mkdir($dir.'/Resources/public/images');
97 | $this->filesystem->mkdir($dir.'/Resources/public/js');
98 | }
99 | }
100 |
101 | /**
102 | * @param string $namespace
103 | * @param string $bundle
104 | * @param string $dir
105 | * @param string $dbDriver
106 | * @param string $basename
107 | */
108 | private function generateModels($namespace, $bundle, $dir, $dbDriver, $basename)
109 | {
110 | $parameters = array(
111 | 'namespace' => $namespace,
112 | 'bundle' => $bundle,
113 | 'bundle_basename' => $basename,
114 | 'extension_alias' => Container::underscore($basename),
115 | );
116 |
117 | $driverDir = array(
118 | 'orm' => 'Entity',
119 | 'mongodb' => 'Document',
120 | 'couchdb' => 'CouchDocument',
121 | 'custom' => 'Model',
122 | );
123 |
124 | $dir = $dir.'/'.$driverDir[$dbDriver];
125 |
126 | $this->renderFile('bundle/model/user_'.$dbDriver.'.php.twig', $dir.'/User.php', $parameters);
127 | $this->renderFile('bundle/model/group_'.$dbDriver.'.php.twig', $dir.'/Group.php', $parameters);
128 | }
129 |
130 | /**
131 | * @param string $namespace
132 | * @param string $bundle
133 | * @param string $dir
134 | * @param string $format
135 | * @param string $basename
136 | */
137 | private function generateRoutes($namespace, $bundle, $dir, $format, $basename)
138 | {
139 | $baseRoutes = array(
140 | 'change_password' => array(
141 | 'change_password' => array(
142 | 'path' => '/change-password',
143 | 'method' => array('GET', 'POST'),
144 | 'controller_action' => 'FOSUserBundle:ChangePassword:changePassword',
145 | ),
146 | ),
147 |
148 | 'group' => array(
149 | 'group_list' => array(
150 | 'path' => '/list',
151 | 'method' => array('GET'),
152 | 'controller_action' => 'FOSUserBundle:Group:list',
153 | ),
154 | 'group_new' => array(
155 | 'path' => '/new',
156 | 'method' => array(),
157 | 'controller_action' => 'FOSUserBundle:Group:new',
158 | ),
159 | 'group_show' => array(
160 | 'path' => '/{groupName}',
161 | 'method' => array('GET'),
162 | 'controller_action' => 'FOSUserBundle:Group:show',
163 | ),
164 | 'group_edit' => array(
165 | 'path' => '/{groupName}/edit',
166 | 'method' => array(),
167 | 'controller_action' => 'FOSUserBundle:Group:edit',
168 | ),
169 | 'group_delete' => array(
170 | 'path' => '/{groupName}/delete',
171 | 'method' => array('GET'),
172 | 'controller_action' => 'FOSUserBundle:Group:delete',
173 | ),
174 | ),
175 |
176 | 'profile' => array(
177 | 'profile_show' => array(
178 | 'path' => '/',
179 | 'method' => array('GET'),
180 | 'controller_action' => 'FOSUserBundle:Profile:show',
181 | ),
182 | 'profile_edit' => array(
183 | 'path' => '/edit',
184 | 'method' => array(),
185 | 'controller_action' => 'FOSUserBundle:Profile:edit',
186 | ),
187 | ),
188 |
189 | 'registration' => array(
190 | 'registration_register' => array(
191 | 'path' => '/',
192 | 'method' => array(),
193 | 'controller_action' => 'FOSUserBundle:Registration:register',
194 | ),
195 | 'registration_check_email' => array(
196 | 'path' => '/check-email',
197 | 'method' => array('GET'),
198 | 'controller_action' => 'FOSUserBundle:Registration:checkEmail',
199 | ),
200 | 'registration_confirm' => array(
201 | 'path' => '/confirm/{token}',
202 | 'method' => array('GET'),
203 | 'controller_action' => 'FOSUserBundle:Registration:confirm',
204 | ),
205 | 'registration_confirmed' => array(
206 | 'path' => '/confirmed',
207 | 'method' => array('GET'),
208 | 'controller_action' => 'FOSUserBundle:Registration:confirmed',
209 | ),
210 | ),
211 |
212 | 'resetting' => array(
213 | 'resetting_request' => array(
214 | 'path' => '/request',
215 | 'method' => array('GET'),
216 | 'controller_action' => 'FOSUserBundle:Resetting:request',
217 | ),
218 | 'resetting_send_email' => array(
219 | 'path' => '/send-email',
220 | 'method' => array('POST'),
221 | 'controller_action' => 'FOSUserBundle:Resetting:sendEmail',
222 | ),
223 | 'resetting_check_email' => array(
224 | 'path' => '/check-email',
225 | 'method' => array('GET'),
226 | 'controller_action' => 'FOSUserBundle:Resetting:checkEmail',
227 | ),
228 | 'resetting_reset' => array(
229 | 'path' => '/reset/{token}',
230 | 'method' => array('GET', 'POST'),
231 | 'controller_action' => 'FOSUserBundle:Resetting:reset',
232 | ),
233 | ),
234 |
235 | 'security' => array(
236 | 'security_login' => array(
237 | 'path' => '/login',
238 | 'method' => array(),
239 | 'controller_action' => 'FOSUserBundle:Security:login',
240 | ),
241 | 'security_check' => array(
242 | 'path' => '/login_check',
243 | 'method' => array('POST'),
244 | 'controller_action' => 'FOSUserBundle:Security:check',
245 | ),
246 | 'security_logout' => array(
247 | 'path' => '/logout',
248 | 'method' => array(),
249 | 'controller_action' => 'FOSUserBundle:Security:logout',
250 | ),
251 | ),
252 | );
253 |
254 | foreach ($baseRoutes as $fileName => $routes) {
255 | $parameters = array(
256 | 'namespace' => $namespace,
257 | 'bundle' => $bundle,
258 | 'format' => $format,
259 | 'bundle_basename' => $basename,
260 | 'extension_alias' => Container::underscore($basename),
261 | 'routes' => $routes,
262 | );
263 |
264 | $this->renderFile('bundle/routing.'.$format.'.twig', $dir.'/Resources/config/routing/'.$fileName.'.'.$format, $parameters);
265 | }
266 | }
267 |
268 | private function generateEventsClass($namespace, $bundle, $dir, $format, $basename)
269 | {
270 | $eventsClass = new \ReflectionClass('FOS\UserBundle\FOSUserEvents');
271 | $events = $eventsClass->getConstants();
272 |
273 | foreach ($events as $name => $event) {
274 | $events[$name] = Container::underscore($basename).substr($event, 8);
275 | }
276 |
277 | $parameters = array(
278 | 'namespace' => $namespace,
279 | 'bundle' => $bundle,
280 | 'format' => $format,
281 | 'bundle_basename' => $basename,
282 | 'extension_alias' => Container::underscore($basename),
283 | 'events' => $events,
284 | );
285 |
286 | $this->renderFile('bundle/Events.php.twig', $dir.'/'.$basename.'Events.php', $parameters);
287 | }
288 | }
289 |
--------------------------------------------------------------------------------
/src/Command/GenerateUserSysCommand.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace Rollerworks\Bundle\MultiUserBundle\Command;
13 |
14 | use Rollerworks\Bundle\MultiUserBundle\Generator\UserBundleGenerator;
15 | use Sensio\Bundle\GeneratorBundle\Command\GenerateBundleCommand;
16 | use Symfony\Component\Console\Input\InputInterface;
17 | use Symfony\Component\Console\Input\InputOption;
18 | use Symfony\Component\Console\Output\OutputInterface;
19 | use Symfony\Component\HttpKernel\Bundle\BundleInterface;
20 |
21 | class GenerateUserSysCommand extends GenerateBundleCommand
22 | {
23 | protected function configure()
24 | {
25 | parent::configure();
26 | $this->setName('rollerworks:multi-user:generate:usersys');
27 |
28 | $definition = $this->getDefinition();
29 | $definition->addOption(new InputOption('db-driver', '', InputOption::VALUE_REQUIRED, 'DB-driver to use'));
30 |
31 | $this
32 | ->setHelp(<<rollerworks:multi-user:generate:usersys command helps you generates new user-system bundles.
34 |
35 | By default, the command interacts with the developer to tweak the generation.
36 | Any passed option will be used as a default value for the interaction
37 | (--namespace is the only one needed if you follow the
38 | conventions):
39 |
40 | php app/console rollerworks:multi-user:generate:usersys --namespace=Acme/UserBundle
41 |
42 | Note that you can use / instead of \\ for the namespace delimiter to avoid any
43 | problem.
44 |
45 | If you want to disable any user interaction, use --no-interaction but don't forget to pass all needed options:
46 |
47 | php app/console rollerworks:multi-user:generate:usersys --namespace=Acme/UserBundle --dir=src [--db-driver=...] [--bundle-name=...] --no-interaction
48 |
49 | Note that the bundle namespace must end with "Bundle".
50 | EOT
51 | );
52 | }
53 |
54 | /**
55 | * @see Command
56 | *
57 | * @throws \InvalidArgumentException When namespace doesn't end with Bundle
58 | * @throws \RuntimeException When bundle can't be executed
59 | */
60 | protected function execute(InputInterface $input, OutputInterface $output)
61 | {
62 | $questionHelper = $this->getQuestionHelper();
63 | $dialog = $this->getHelper('dialog');
64 |
65 | if ($input->isInteractive()) {
66 | if (!$dialog->askConfirmation($output, $questionHelper->getQuestion('Do you confirm generation', 'yes', '?'), true)) {
67 | $output->writeln('Command aborted ');
68 |
69 | return 1;
70 | }
71 | }
72 |
73 | foreach (array('namespace', 'dir') as $option) {
74 | if (null === $input->getOption($option)) {
75 | throw new \RuntimeException(sprintf('The "%s" option must be provided.', $option));
76 | }
77 | }
78 |
79 | $namespace = Validators::validateBundleNamespace($input->getOption('namespace'));
80 | if (!$bundle = $input->getOption('bundle-name')) {
81 | $bundle = strtr($namespace, array('\\' => ''));
82 | }
83 | $bundle = Validators::validateBundleName($bundle);
84 | $dir = Validators::validateTargetDir($input->getOption('dir'), $bundle, $namespace);
85 |
86 | if (null === $input->getOption('format')) {
87 | $input->setOption('format', 'xml');
88 | }
89 | $format = Validators::validateFormat($input->getOption('format'));
90 | $structure = $input->getOption('structure');
91 |
92 | if (null === $input->getOption('db-driver')) {
93 | $input->setOption('db-driver', 'orm');
94 | }
95 | $dbDriver = Validators::validateDbDriver($input->getOption('db-driver'));
96 |
97 | $questionHelper->writeSection($output, 'Bundle generation');
98 |
99 | if (!$this->getContainer()->get('filesystem')->isAbsolutePath($dir)) {
100 | $dir = getcwd().'/'.$dir;
101 | }
102 |
103 | $generator = $this->getGenerator();
104 | $generator->generate($namespace, $bundle, $dir, $format, $structure, $dbDriver);
105 |
106 | $output->writeln('Generating the bundle code: OK ');
107 |
108 | $errors = array();
109 | $runner = $questionHelper->getRunner($output, $errors);
110 |
111 | // check that the namespace is already autoloaded
112 | $runner($this->checkAutoloader($output, $namespace, $bundle, $dir));
113 |
114 | // register the bundle in the Kernel class
115 | $runner($this->updateKernel($questionHelper, $input, $output, $this->getContainer()->get('kernel'), $namespace, $bundle));
116 |
117 | $questionHelper->writeGeneratorSummary($output, $errors);
118 | }
119 |
120 | protected function interact(InputInterface $input, OutputInterface $output)
121 | {
122 | $questionHelper = $this->getQuestionHelper();
123 | $dialog = $this->getHelper('dialog');
124 |
125 | $questionHelper->writeSection($output, 'Welcome to the RollerworksMultiUser UserSys-bundle generator');
126 |
127 | // namespace
128 | $namespace = null;
129 | try {
130 | $namespace = $input->getOption('namespace') ? Validators::validateBundleNamespace($input->getOption('namespace')) : null;
131 | } catch (\Exception $error) {
132 | $output->writeln($questionHelper->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error'));
133 | }
134 |
135 | if (null === $namespace) {
136 | $output->writeln(array(
137 | '',
138 | 'Your user-systems code must be written in bundles . This command helps',
139 | 'you generate them easily.',
140 | '',
141 | 'Each user-system bundle is hosted under a namespace (like Acme/Bundle/UserBundle ).',
142 | 'The namespace should begin with a "vendor" name like your company name, your',
143 | 'project name, or your client name, followed by one or more optional category',
144 | 'sub-namespaces, and it should end with the bundle name itself',
145 | '(which must have Bundle as a suffix).',
146 | '',
147 | 'See http://symfony.com/doc/current/cookbook/bundles/best_practices.html#index-1 for more',
148 | 'details on bundle naming conventions.',
149 | '',
150 | 'Use / instead of \\ for the namespace delimiter to avoid any problem.',
151 | '',
152 | ));
153 |
154 | $namespace = $dialog->askAndValidate($output, $questionHelper->getQuestion('Bundle namespace', $input->getOption('namespace')), array('Rollerworks\Bundle\MultiUserBundle\Command\Validators', 'validateBundleNamespace'), false, $input->getOption('namespace'));
155 | $input->setOption('namespace', $namespace);
156 | }
157 |
158 | // bundle name
159 | $bundle = null;
160 | try {
161 | $bundle = $input->getOption('bundle-name') ? Validators::validateBundleName($input->getOption('bundle-name')) : null;
162 | } catch (\Exception $error) {
163 | $output->writeln($questionHelper->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error'));
164 | }
165 |
166 | if (null === $bundle) {
167 | $bundle = strtr($namespace, array('\\Bundle\\' => '', '\\' => ''));
168 |
169 | $output->writeln(array(
170 | '',
171 | 'In your code, a bundle is often referenced by its name. It can be the',
172 | 'concatenation of all namespace parts but it\'s really up to you to come',
173 | 'up with a unique name (a good practice is to start with the vendor name).',
174 | 'Based on the namespace, we suggest '.$bundle.' .',
175 | '',
176 | ));
177 | $bundle = $dialog->askAndValidate($output, $questionHelper->getQuestion('Bundle name', $bundle), array('Rollerworks\Bundle\MultiUserBundle\Command\Validators', 'validateBundleName'), false, $bundle);
178 | $input->setOption('bundle-name', $bundle);
179 | }
180 |
181 | // target dir
182 | $dir = null;
183 | try {
184 | $dir = $input->getOption('dir') ? Validators::validateTargetDir($input->getOption('dir'), $bundle, $namespace) : null;
185 | } catch (\Exception $error) {
186 | $output->writeln($questionHelper->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error'));
187 | }
188 |
189 | if (null === $dir) {
190 | $dir = dirname($this->getContainer()->getParameter('kernel.root_dir')).'/src';
191 |
192 | $output->writeln(array(
193 | '',
194 | 'The bundle can be generated anywhere. The suggested default directory uses',
195 | 'the standard conventions.',
196 | '',
197 | ));
198 | $dir = $dialog->askAndValidate($output, $questionHelper->getQuestion('Target directory', $dir), function ($dir) use ($bundle, $namespace) { return Validators::validateTargetDir($dir, $bundle, $namespace); }, false, $dir);
199 | $input->setOption('dir', $dir);
200 | }
201 |
202 | // format
203 | $format = null;
204 | try {
205 | $format = $input->getOption('format') ? Validators::validateFormat($input->getOption('format')) : null;
206 | } catch (\Exception $error) {
207 | $output->writeln($questionHelper->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error'));
208 | }
209 |
210 | if (null === $format) {
211 | $output->writeln(array(
212 | '',
213 | 'Determine the format to use for the generated configuration, note that annotation is not supported.',
214 | '',
215 | ));
216 | $format = $dialog->askAndValidate($output, $questionHelper->getQuestion('Configuration format (yml, xml or php)', $input->getOption('format')), array('Rollerworks\Bundle\MultiUserBundle\Command\Validators', 'validateFormat'), false, $input->getOption('format'));
217 | $input->setOption('format', $format);
218 | }
219 |
220 | // db-driver
221 | $dbDriver = null;
222 | try {
223 | $dbDriver = $input->getOption('db-driver') ?: null;
224 | } catch (\Exception $error) {
225 | $output->writeln($questionHelper->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error'));
226 | }
227 |
228 | if (null === $dbDriver) {
229 | $output->writeln(array(
230 | '',
231 | 'For the user-system to work you need to configure a db-driver.',
232 | '',
233 | ));
234 | $dbDriver = $dialog->askAndValidate($output, $questionHelper->getQuestion('Db-driver (orm, mongodb, couchdb or custom)', $input->getOption('db-driver')), array('Rollerworks\Bundle\MultiUserBundle\Command\Validators', 'validateDbDriver'), false, $input->getOption('db-driver'));
235 | $input->setOption('db-driver', $dbDriver);
236 | }
237 |
238 | // optional files to generate
239 | $output->writeln(array(
240 | '',
241 | 'To help you get started faster, the command can generate some',
242 | 'code snippets for you.',
243 | '',
244 | ));
245 |
246 | $structure = $input->getOption('structure');
247 | if (!$structure && $dialog->askConfirmation($output, $questionHelper->getQuestion('Do you want to generate the whole directory structure', 'no', '?'), false)) {
248 | $structure = true;
249 | }
250 | $input->setOption('structure', $structure);
251 |
252 | // summary
253 | $output->writeln(array(
254 | '',
255 | $this->getHelper('formatter')->formatBlock('Summary before generation', 'bg=blue;fg=white', true),
256 | '',
257 | sprintf("You are going to generate a \"%s\\%s \" bundle\nin \"%s \" using the \"%s \" format with db-driver \"%s\".", $namespace, $bundle, $dir, $format, $dbDriver),
258 | '',
259 | ));
260 | }
261 |
262 | protected function createGenerator()
263 | {
264 | return new UserBundleGenerator($this->getContainer()->get('filesystem'));
265 | }
266 |
267 | /**
268 | * add this bundle skeleton dirs to the beginning of the parent skeletonDirs array.
269 | *
270 | * @param BundleInterface $bundle
271 | *
272 | * @return string[]
273 | */
274 | protected function getSkeletonDirs(BundleInterface $bundle = null)
275 | {
276 | $baseSkeletonDirs = parent::getSkeletonDirs($bundle);
277 | $skeletonDirs = array();
278 |
279 | if (is_dir($dir = $this->getContainer()->get('kernel')->getRootdir().'/Resources/MultiUserBundleMultiUserBundle/skeleton')) {
280 | $skeletonDirs[] = $dir;
281 | }
282 |
283 | $reflClass = new \ReflectionClass($this);
284 | $dir = dirname($reflClass->getFileName());
285 |
286 | $skeletonDirs[] = $dir.'/../Resources/skeleton';
287 | $skeletonDirs[] = $dir.'/../Resources';
288 |
289 | return array_merge($skeletonDirs, $baseSkeletonDirs);
290 | }
291 | }
292 |
--------------------------------------------------------------------------------