3

I'm defining a few new roles in the install hook of my module and one of them is an "admin light" role, which will need some, but not all of the admin account permissions.

I need to pragmatically build a list of available permissions from a pre-defined list of modules (User, Node, Toolbar, etc) and assign them to the role. Without having to hard code all of the permission strings.

In Drupal 7 I could do something like:

$modules = array( 'user', 'node', 'toolbar' );
foreach( $modules as $module) {    
 $permission_hook = $module . '_permisson';
 if( module_exists( $module ) && function_exists( $permission_hook ) ) {
  user_role_grant_permissions( $rid, array_keys( $permission_hook() ) );
 }
}

I'm struggling to find an solution as neat for Drupal 8 seeing as hook_permssion has been removed in favor of $module.permission.yml. Is there something I'm missing?

EDIT: Final Solution: This is the final implementation, just in case anyone else need to do this:

  // Define our new roles
  $roles = array(
    array(
      'id' => 'mymodule_client',
      'label' => 'Client',
      'mymodule_permissions' => array(
        'view project status reports',
      ),
    ),
    array(
      'id' => 'mymodule_agent',
      'label' => 'Agent',
      'mymodule_permissions' => array(
        'view projects',
        'view project status reports',
      ),
    ),
    array(
      'id' => 'mymodule_agent_manager',
      'label' => 'Agent Manager',
      'mymodule_permissions' => array(
        'view projects',
        'administer projects',
        'view project status reports',
      ),
    ),
    array(
      'id' => 'mymodule_employee',
      'label' => 'Employee',
      'mymodule_permissions' => array(
        'view projects',
        'administer projects',
        'view project status reports',
        'view project financial reports',
      ),
      // Assign all permissions for the listed modules to this role
      'provider_permissions' => array(
        'user', 'node', 'toolbar'
      ),
    ),
  );

  // At the default level all roles should have the same permissions as authenticated users
  $permissions = Role::load( Role::AUTHENTICATED_ID )->getPermissions();
  // Get permissions for all modules and add them to an array keyed by the module
  $provider_permissions = array();
  foreach( \Drupal::service('user.permissions')->getPermissions() as $key => $permission ) {
    $provider_permissions[ $permission['provider'] ][] = $key;
  }
  // Lets loop our new permissions and create them
  foreach( $roles as $role_values ) {
    // Merge our modules bespoke permissions with the authenticated role permissions
    $permissions = array_merge( $permissions, $role_values['mymodule_permissions'] );
    // Remove our module permissions before we create the role
    unset( $role_values['mymodule_permissions'] );
    // If the role needs access to other module permissions merge them in
    if( isset( $role_values['provider_permissions'] ) && is_array( $role_values['provider_permissions'] ) ) {
      foreach( $role_values['provider_permissions'] as $module ) {
        if( array_key_exists( $module, $provider_permissions ) ) {
          $permissions = array_merge( $permissions, $provider_permissions[ $module ] );
        }
      }
      // Remove the module_permissions before we build the role
      unset( $role_values['provider_permissions'] );
    }
    // Create the role
    $role = Role::create( $role_values );
    // Assign all the required permissions
    foreach( $permissions as $permission ) {
      $role->grantPermission( $permission );
    }
    // Save the role
    $role->save();
  }

This code uses the authenticated role as a base, then adds our module permissions (defined per role), and then adds any other modules permissions to roles that require them.

6

You can list all available permissions with PermissionHandler:

$permissions = \Drupal::service('user.permissions')->getPermissions();

You'll find the module name in the provider property of the permissions:

$permissions_by_provider = [];
foreach ($permissions as $key => $permission) {
  $permissions_by_provider[$permission['provider']][] = $key;
}
  • That's what I was after. Seems a shame that you can't pass the provider as an argument to filter against. Thanks very much for your help. – Lyndon Cox Feb 28 '17 at 14:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.