问题
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:
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?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