diff --git a/Controller/PermissionsGroupController.php b/Controller/PermissionsGroupController.php
index b0f0fadab..38b893e74 100644
--- a/Controller/PermissionsGroupController.php
+++ b/Controller/PermissionsGroupController.php
@@ -108,6 +108,8 @@ class PermissionsGroupController extends Controller
$translatableStringHelper = $this->get('chill.main.helper.translatable_string');
$roleScopes = $permissionsGroup->getRoleScopes()->toArray();
+
+ // sort $roleScopes by name
usort($roleScopes,
function(RoleScope $a, RoleScope $b) use ($translatableStringHelper) {
if ($a->getScope() === NULL) {
@@ -122,10 +124,21 @@ class PermissionsGroupController extends Controller
$translatableStringHelper->localize($b->getScope()->getName())
);
});
-
+
+ // sort role scope by title
+ /* @var $roleProvider \Chill\MainBundle\Security\RoleProvider */
+ $roleProvider = $this->get('chill.main.role_provider');
+ $roleScopesSorted = array();
+ foreach($roleScopes as $roleScope) {
+ /* @var $roleScope RoleScope */
+ $title = $roleProvider->getRoleTitle($roleScope->getRole());
+ $roleScopesSorted[$title][] = $roleScope;
+ }
+ ksort($roleScopesSorted);
+
return $this->render('ChillMainBundle:PermissionsGroup:show.html.twig', array(
'entity' => $permissionsGroup,
- 'role_scopes' => $roleScopes,
+ 'role_scopes_sorted' => $roleScopesSorted,
'expanded_roles' => $this->getExpandedRoles($roleScopes)
));
}
@@ -171,6 +184,7 @@ class PermissionsGroupController extends Controller
throw $this->createNotFoundException('Unable to find PermissionsGroup entity.');
}
+ // create all the forms
$editForm = $this->createEditForm($permissionsGroup);
$deleteRoleScopesForm = array();
@@ -180,9 +194,21 @@ class PermissionsGroupController extends Controller
}
$addRoleScopesForm = $this->createAddRoleScopeForm($permissionsGroup);
+
+ // sort role scope by title
+ /* @var $roleProvider \Chill\MainBundle\Security\RoleProvider */
+ $roleProvider = $this->get('chill.main.role_provider');
+ $roleScopesSorted = array();
+ foreach($permissionsGroup->getRoleScopes()->toArray() as $roleScope) {
+ /* @var $roleScope RoleScope */
+ $title = $roleProvider->getRoleTitle($roleScope->getRole());
+ $roleScopesSorted[$title][] = $roleScope;
+ }
+ ksort($roleScopesSorted);
return $this->render('ChillMainBundle:PermissionsGroup:edit.html.twig', array(
'entity' => $permissionsGroup,
+ 'role_scopes_sorted' => $roleScopesSorted,
'edit_form' => $editForm->createView(),
'expanded_roles' => $this->getExpandedRoles($permissionsGroup->getRoleScopes()->toArray()),
'delete_role_scopes_form' => array_map( function($form) {
diff --git a/Form/Type/ComposedRoleScopeType.php b/Form/Type/ComposedRoleScopeType.php
index 194fa6f15..966f30908 100644
--- a/Form/Type/ComposedRoleScopeType.php
+++ b/Form/Type/ComposedRoleScopeType.php
@@ -56,12 +56,20 @@ class ComposedRoleScopeType extends AbstractType
*/
private $translatableStringHelper;
- public function __construct(TranslatableStringHelper $translatableStringHelper,
- RoleProvider $roleProvider)
- {
+ /**
+ *
+ * @var RoleProvider
+ */
+ private $roleProvider;
+
+ public function __construct(
+ TranslatableStringHelper $translatableStringHelper,
+ RoleProvider $roleProvider
+ ) {
$this->roles = $roleProvider->getRoles();
$this->rolesWithoutScope = $roleProvider->getRolesWithoutScopes();
$this->translatableStringHelper = $translatableStringHelper;
+ $this->roleProvider = $roleProvider;
}
public function buildForm(FormBuilderInterface $builder, array $options)
@@ -86,6 +94,9 @@ class ComposedRoleScopeType extends AbstractType
} else {
return array('data-has-scope' => '1');
}
+ },
+ 'group_by' => function($role, $key, $index) {
+ return $this->roleProvider->getRoleTitle($role);
}
))
->add('scope', 'entity', array(
diff --git a/Resources/views/PermissionsGroup/edit.html.twig b/Resources/views/PermissionsGroup/edit.html.twig
index 75dce3f40..43ffd6a62 100644
--- a/Resources/views/PermissionsGroup/edit.html.twig
+++ b/Resources/views/PermissionsGroup/edit.html.twig
@@ -15,6 +15,10 @@
{{ 'Grant those permissions'|trans }} :
{%- if entity.getRoleScopes|length > 0 -%}
+ {% for title, role_scopes in role_scopes_sorted %}
+
+ {{ title|default("Unclassified")|trans }}
+
@@ -25,7 +29,7 @@
- {% for role_scope in entity.getRoleScopes %}
+ {% for role_scope in role_scopes %}
{{ role_scope.role|trans }}
@@ -53,6 +57,7 @@
{% endfor %}
|
+ {% endfor %}
{%- else -%}
{{ 'This group does not provide any permission'|trans }}
@@ -64,15 +69,24 @@
{{ form_errors(add_role_scopes_form) }}
{{ form_row(add_role_scopes_form.composed_role_scope.role) }}
{{ form_row(add_role_scopes_form.composed_role_scope.scope) }}
- {{ form_row(add_role_scopes_form.submit, { 'attr' : { 'class': 'sc-button green' } } ) }}
+
+
+
+
{{ form_end(add_role_scopes_form) }}
-
+
{% endblock %}
diff --git a/Resources/views/PermissionsGroup/index.html.twig b/Resources/views/PermissionsGroup/index.html.twig
index d28790177..cc5f6c053 100644
--- a/Resources/views/PermissionsGroup/index.html.twig
+++ b/Resources/views/PermissionsGroup/index.html.twig
@@ -17,12 +17,12 @@
{{ entity.name }} |
- |
@@ -31,9 +31,9 @@
-
+
-
-
+
{{ 'Create a new permissions group'| trans }}
diff --git a/Resources/views/PermissionsGroup/show.html.twig b/Resources/views/PermissionsGroup/show.html.twig
index d28c9548b..e2d49a6f1 100644
--- a/Resources/views/PermissionsGroup/show.html.twig
+++ b/Resources/views/PermissionsGroup/show.html.twig
@@ -13,9 +13,11 @@
- {% if role_scopes|length > 0 %}
+ {% if role_scopes_sorted|length > 0 %}
{{ 'Grant those permissions'|trans }} :
-
+
+ {% for title, role_scopes in role_scopes_sorted %}
+ {{ title|default('Unclassified')|trans }}
@@ -24,6 +26,7 @@
+
{% for role_scope in role_scopes %}
@@ -43,6 +46,7 @@
{% endfor %}
|
+ {% endfor %}
{% else %}
@@ -51,16 +55,18 @@
{{ 'add permissions'|trans|capitalize }}
{% endif %}
-
+
{% endblock %}
diff --git a/Security/ProvideRoleHierarchyInterface.php b/Security/ProvideRoleHierarchyInterface.php
new file mode 100644
index 000000000..d5f49db5d
--- /dev/null
+++ b/Security/ProvideRoleHierarchyInterface.php
@@ -0,0 +1,42 @@
+
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+namespace Chill\MainBundle\Security;
+
+/**
+ * Give a hierarchy for the role.
+ *
+ * This hierarchy allow to sort roles, which is useful in UI
+ *
+ * @author Julien Fastré
+ */
+interface ProvideRoleHierarchyInterface extends ProvideRoleInterface
+{
+ /**
+ * Return an array of roles, where keys are the hierarchy, and values
+ * an array of roles.
+ *
+ * Example:
+ *
+ * ```
+ * [ 'Title' => [ 'CHILL_FOO_SEE', 'CHILL_FOO_UPDATE' ] ]
+ * ```
+ *
+ * @return array where keys are the hierarchy, and values an array of roles: `[ 'title' => [ 'CHILL_FOO_SEE', 'CHILL_FOO_UPDATE' ] ]`
+ */
+ public function getRolesWithHierarchy();
+}
diff --git a/Security/RoleProvider.php b/Security/RoleProvider.php
index e206e64b4..f72435cb1 100644
--- a/Security/RoleProvider.php
+++ b/Security/RoleProvider.php
@@ -32,6 +32,16 @@ class RoleProvider
*/
private $providers = array();
+ /**
+ * an array where keys are the role, and value is the title
+ * for the given role.
+ *
+ * Null when not initialized.
+ *
+ * @var array|null
+ */
+ private $rolesTitlesCache = null;
+
/**
* Add a role provider
*
@@ -75,4 +85,52 @@ class RoleProvider
return $roles;
}
+ /**
+ * initialize the array for caching role and titles
+ *
+ */
+ private function initializeRolesTitlesCache()
+ {
+ // break if already initialized
+ if ($this->rolesTitlesCache !== null) {
+ return;
+ }
+
+ foreach ($this->providers as $provider) {
+ if ($provider instanceof ProvideRoleHierarchyInterface) {
+ foreach ($provider->getRolesWithHierarchy() as $title => $roles) {
+ foreach($roles as $role) {
+ $this->rolesTitlesCache[$role] = $title;
+ }
+ }
+ } else {
+ if ($provider->getRoles() !== null) {
+ $this->rolesTitlesCache = \array_merge(
+ $this->rolesTitlesCache,
+ \array_fill_keys($provider->getRoles(), null)
+ );
+ }
+ }
+ }
+ }
+
+ /**
+ * Get the title for each role.
+ *
+ * @param string $role
+ * @return string the title of the role
+ */
+ public function getRoleTitle($role)
+ {
+ $this->initializeRolesTitlesCache();
+
+ if (! \array_key_exists($role, $this->rolesTitlesCache)) {
+ // this case might happens when the role is not described in
+ // `getRolesWithHierarchy`
+ return null;
+ }
+
+ return $this->rolesTitlesCache[$role];
+ }
+
}