This forum has moved to a new location and is in read-only mode. Please visit talk.octobercms.com to access the new location.

info51886
info51886

Hi guys,

I'm extending the backend \Backend\Models\User model, and I would like to override the getRoleOptions() method that populates the radio buttons to choose a user's role with a version that omits the default system roles when the current user is not a super user.

In my Plugin.php file, I have placed the following code in my boot() method:

\Backend\Models\User::extend(function ($model) {
    $model->addDynamicMethod('getRoleOptions', function () {
        foreach (UserRole::all() as $role) {
            // Hide built-in system roles unless the user is a super user
            if (!BackendAuth::getUser()->isSuperUser() && $role->is_system) {
                continue;
            }

            $result[$role->id] = [$role->name, $role->description];
        }

        return $result;
    }
}

Unfortunately, this does not work. I know that my code is not the issue, because it works fine when I manually comment out the getRoleOptions() method in the built in User model, but that is obviously not an ideal solution.

So is there a way to override a pre-existing method using addDynamicMethod() or some other way, or is this simply not possible?

Update:

I have figured out a workaround, it's not ideal but it seems to work reliably.

First I added a 2nd role field called user_role:

Event::listen('backend.form.extendFields', function($widget) {
    if (!$widget->getController() instanceof \Backend\Controllers\Users) {
        return;
    }

    if (!$widget->model instanceof \Backend\Models\User) {
        return;
    }

    $widget->addTabFields([
        'user_role' => [
            'label'  => 'Role',
            'commentAbove' => 'Roles define user permissions, which can be overriden on the user level, on the Permissions tab.',
            'type' => 'radio',
            'required' => 1,
        ],
    ]);
}

Then I:

  • Made the original role field fillable (it's guarded by default)
  • Populated the field with the roles I want to show
  • When saving the form, I reassign the value from the 2nd role field to the original role field
\Backend\Models\User::extend(function ($model) {
    // Make the original role field fillable
    $model->addFillable(['role']);

    // Populate the field with the desired roles
    $model->addDynamicMethod('getUserRoleOptions', function () {
        foreach (UserRole::all() as $role) {
            // Hide built-in system roles unless the user is a super user
            if (!BackendAuth::getUser()->isSuperUser() && $role->is_system) {
                continue;
            }

            $result[$role->id] = [$role->name, $role->description];
        }

        return $result;
    }

    // Reassign the value from the 2nd role field to the original role field
    $model->bindEvent('model.beforeSave', function () use ($model) {
        $model->role = $model->user_role;
    });
}

I'm still not very excited about making the original role field fillable, so I am still open to suggestions to improve this solution.

Last updated

Sam Georges
Sam Georges

Hello,

This is one way to do it. Another way might be to extend the form field and replacing the options value with a reference to your own logic, however, it is not easy to do this in the current release. It will become easier in v2.2 when the method getField becomes available.

It lets you do this instead of the addTabFields call:

$this->getField('role')->options(function() { return []; });

As a side note, this is available now if you want to try October v3 beta.

1-2 of 2

You cannot edit posts or make replies: the forum has moved to talk.octobercms.com.