set role for users in edit form of sonata admin

微笑、不失礼 提交于 2019-12-12 09:46:25

问题


I'm using Symfony 2.1 for a project. I use the FOSUserBundle for managing users & SonataAdminBundle for administration usage.

I have some questions about that:

  1. As an admin, I want to set roles from users in users edit form. How can I have access to roles in role_hierarchy? And how can I use them as choice fields so the admin can set roles to users?

  2. When I show roles in a list, it is shown as string like this:

    [0 => ROLE_SUPER_ADMIN] [1 => ROLE_USER] 
    

    How can I change it to this?

    ROLE_SUPER_ADMIN, ROLE_USER 
    

    I mean, having just the value of the array.


回答1:


Based on the answer of @parisssss although it was wrong, here is a working solution. The Sonata input field will show all the roles that are under the given role if you save one role.

On the other hand, in the database will be stored only the most important role. But that makes absolute sense in the Sf way.

protected function configureFormFields(FormMapper $formMapper) {
// ..
$container = $this->getConfigurationPool()->getContainer();
$roles = $container->getParameter('security.role_hierarchy.roles');

$rolesChoices = self::flattenRoles($roles);

$formMapper
    //...
    ->add('roles', 'choice', array(
           'choices'  => $rolesChoices,
           'multiple' => true
        )
    );

And in another method:

/**
 * Turns the role's array keys into string <ROLES_NAME> keys.
 * @todo Move to convenience or make it recursive ? ;-)
 */
protected static function flattenRoles($rolesHierarchy) 
{
    $flatRoles = array();
    foreach($rolesHierarchy as $roles) {

        if(empty($roles)) {
            continue;
        }

        foreach($roles as $role) {
            if(!isset($flatRoles[$role])) {
                $flatRoles[$role] = $role;
            }
        }
    }

    return $flatRoles;
}

See it in action:




回答2:


As for the second question I added a method in the User class that looks like this

/**
 * @return string
 */
 public function getRolesAsString()
 {
     $roles = array();
     foreach ($this->getRoles() as $role) {
        $role = explode('_', $role);
        array_shift($role);
        $roles[] = ucfirst(strtolower(implode(' ', $role)));
     }

     return implode(', ', $roles);
 }

And then you can declare in your configureListFields function:

->add('rolesAsString', 'string')



回答3:


i found an answer for my first question!(but the second one in not answered yet..) i add the roles like below in configureFormFields function :

  protected function configureFormFields(FormMapper $formMapper) {
  //..
 $formMapper
 ->add('roles','choice',array('choices'=>$this->getConfigurationPool()->getContainer()->getParameter('security.role_hierarchy.roles'),'multiple'=>true ));
}

I would be very happy if anyone answers the second question :)




回答4:


Romain Bruckert's solution is almost perfect, except that it doesn't allow to set roles, which are roots of role hierrarchy. For instance ROLE_SUPER_ADMIN. Here's the fixed method flattenRoles, which also returns root roles:

protected static function flattenRoles($rolesHierarchy)
{
    $flatRoles = [];
    foreach ($rolesHierarchy as $key => $roles) {
        $flatRoles[$key] = $key;
        if (empty($roles)) {
            continue;
        }

        foreach($roles as $role) {
            if(!isset($flatRoles[$role])) {
                $flatRoles[$role] = $role;
            }
        }
    }

    return $flatRoles;
}

Edit: TrtG already posted this fix in comments




回答5:


Just to overplay it a bit, here is my enhanced version of Romain Bruckert and Sash which gives you an array like this:

array:4 [▼
  "ROLE_USER" => "User"
  "ROLE_ALLOWED_TO_SWITCH" => "Allowed To Switch"
  "ROLE_ADMIN" => "Admin (User, Allowed To Switch)"
  "ROLE_SUPER_ADMIN" => "Super Admin (Admin (User, Allowed To Switch))"
]

This helps you find all roles, that include a specific role:

I know its much code, it could be done much better, but maybe it helps somebody or you can at least use pieces of this code.

/**
 * Turns the role's array keys into string <ROLES_NAME> keys.
 * @param array $rolesHierarchy
 * @param bool $niceName
 * @param bool $withChildren
 * @param bool $withGrandChildren
 * @return array
 */
protected static function flattenRoles($rolesHierarchy, $niceName = false, $withChildren = false, $withGrandChildren = false)
{
    $flatRoles = [];
    foreach ($rolesHierarchy as $key => $roles) {
        if(!empty($roles)) {
            foreach($roles as $role) {
                if(!isset($flatRoles[$role])) {
                    $flatRoles[$role] = $niceName ? self::niceRoleName($role) : $role;
                }
            }
        }
        $flatRoles[$key] = $niceName ? self::niceRoleName($key) : $key;
        if ($withChildren && !empty($roles)) {
            if (!$recursive) {
                if ($niceName) {
                    array_walk($roles, function(&$item) { $item = self::niceRoleName($item);});
                }
                $flatRoles[$key] .= ' (' . join(', ', $roles) . ')';
            } else {
                $childRoles = [];
                foreach($roles as $role) {
                    $childRoles[$role] = $niceName ? self::niceRoleName($role) : $role;
                    if (!empty($rolesHierarchy[$role])) {
                        if ($niceName) {
                            array_walk($rolesHierarchy[$role], function(&$item) { $item = self::niceRoleName($item);});
                        }
                        $childRoles[$role] .= ' (' . join(', ', $rolesHierarchy[$role]) . ')';
                    }
                }
                $flatRoles[$key] .= ' (' . join(', ', $childRoles) . ')';
            }
        }
    }
    return $flatRoles;
}

/**
 * Remove underscors, ROLE_ prefix and uppercase words
 * @param string $role
 * @return string
 */
protected static function niceRoleName($role) {
    return ucwords(strtolower(preg_replace(['/\AROLE_/', '/_/'], ['', ' '], $role)));
}



回答6:


The second answer is below. Add lines in sonata admin yml file .

sonata_doctrine_orm_admin:
    templates:
        types:
            list:
                user_roles: AcmeDemoBundle:Default:user_roles.html.twig

and in user_roles.html.twig files add below lines

{% extends 'SonataAdminBundle:CRUD:base_list_field.html.twig' %}

{% block field %}
    {% for row in value %}
        {{row}}
        {% if not loop.last %}
        ,
        {% endif %}
    {% endfor %}
{% endblock %}

then into your admin controller and inconfigureListFields function add this line

->add('roles', 'user_roles')

hope this will solve your problem



来源:https://stackoverflow.com/questions/15050576/set-role-for-users-in-edit-form-of-sonata-admin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!