# Panel Staff and Privilege Hooks

https://dev.wisecp.com/es/admin-staff-hooks

The ten hooks over staff accounts, privilege groups, departments and panel settings.

## Overview

Everything about who uses the panel lives here: staff accounts, privilege groups, support departments and an administrator’s own preferences.

These hooks share one pattern: what you receive is not the whole record but the **fields that changed**. When nothing changed the array is empty.

## Reference

### Following a staff record being updated

actionadmin.staff_updated

`AdminStaff` only what changed

Runs after an administrator account is updated.

Parameters 3

$idintThe id of the administrator updated.

$dataarrayThe fields that **changed** on the main record: status, address, name, language, privilege or password. It **arrives empty** when none changed: this answers "what changed", not "what the record holds".

$infoarrayThe changed fields on the extra record: signature, notes, display preference and phone.

Return 1

voidThe return is ignored.

Listener PHP

```php
Hook::add('action:admin.staff_updated', 10, function ($id, $data, $info) {
    // The arrays hold what CHANGED, not the whole record.
    if (isset($data['privilege'])) Acme::auditPrivilegeChange($id, $data['privilege']);
});
```

### Following a staff member being removed

actionadmin.staff_deleted

`AdminStaff` the id only

Runs after an administrator account is deleted.

Parameters 1

$idintThe id of the deleted administrator. No record is passed: if you need the name or address you must have kept it beforehand.

Return 1

voidThe return is ignored.

Listener PHP

```php
Hook::add('action:admin.staff_deleted', 10, function ($id) {
    // No record is passed: keep what you need beforehand.
    Acme::revokeAllTokens($id);
});
```

### Following two-step verification being switched off

actionadmin.staff_authentication_disabled

`AdminStaff` security weakens

Runs after two-step verification is switched off for an administrator. It is a **weakening of security** and is usually done by somebody else.

Parameters 2

$idintThe administrator it was switched off for.

$methodstringThe key of the method switched off.

Return 1

voidThe return is ignored.

Listener PHP

```php
Hook::add('action:admin.staff_authentication_disabled', 10, function ($id, $method) {
    // Security just weakened: do not stay quiet.
    Acme::alertSecurityTeam($id, $method);
});
```

### Following a privilege group being saved

actionadmin.privilege_saved

`AdminStaff` id unreliable on create

Runs when a privilege group is created or edited.

Parameters 4

$idintThe id of the group. ? **On the create path it is not the new id** and may be zero. Tell a new record from the operation type, not from this.

$typestringThe operation: `add` or `edit`.

$namestringThe name of the group.

$permsstringThe permission keys as saved, comma separated. It is not an array: split it to work with it.

Return 1

voidThe return is ignored.

Listener PHP

```php
Hook::add('action:admin.privilege_saved', 10, function ($id, $type, $name, $perms) {
    // Tell a new record from the operation TYPE, not the id.
    if ($type === 'add') Acme::noteNewRole($name, explode(',', $perms));
});
```

### Following an administrator updating their own profile

actionadmin.profile_updated

`AdminStaff` their own profile

Runs when an administrator updates their own profile.

Parameters 3

$admin_idintThe administrator whose profile changed.

$data_updatesarrayThe changed fields on the main record: name and address. Empty when nothing changed.

$info_updatesarrayWhat changed on the extra record: the phone fields.

Return 1

voidThe return is ignored.

Listener PHP

```php
Hook::add('action:admin.profile_updated', 10,
    function ($admin_id, $data_updates, $info_updates) {
        if (isset($data_updates['email'])) Acme::alertEmailChange($admin_id);
    });
```

### Following panel preferences changing

actionadmin.preferences_updated

`AdminStaff` display preferences

Runs when an administrator changes how the panel looks for them.

Parameters 3

$admin_idintThe administrator whose preferences changed.

$info_setsarrayThe display preferences that changed: light or dark, and the menu state.

$data_setsarrayWhat changed on the main record: their language.

Return 1

voidThe return is ignored.

Listener PHP

```php
Hook::add('action:admin.preferences_updated', 10,
    function ($admin_id, $info_sets, $data_sets) {
        if (isset($data_sets['lang'])) Acme::syncLocale($admin_id, $data_sets['lang']);
    });
```

### Following a department being saved

actionadmin.department_saved

`AdminStaff` id correct on create

Runs when a support department is created or edited.

Parameters 3

$idintThe department id. Unlike the privilege hook, the id here is **correct on the create path too**.

$typestringThe operation: `add` or `edit`.

$set_dataarrayThe saved fields: rank, appointees and icon.

Return 1

voidThe return is ignored.

Listener PHP

```php
Hook::add('action:admin.department_saved', 10, function ($id, $type, $set_data) {
    // Here the id is correct on the create path as well.
    Acme::syncDepartment($id, $set_data);
});
```

### Following a department being deleted

actionadmin.department_deleted

`AdminStaff` after deletion

Runs after a support department is deleted.

Parameters 2

$idintThe id of the deleted department.

$detailarrayThe record of the deleted department, name included.

Return 1

voidThe return is ignored.

Listener PHP

```php
Hook::add('action:admin.department_deleted', 10, function ($id, $detail) {
    Acme::dropDepartmentRoute($id);
});
```

### Following logs being cleared

actionadmin.logs_cleared

`AdminTools` cannot be undone

Runs when an administrator clears a log type. What is deleted **does not come back**.

Parameters 2

$typestringWhat was cleared: user actions, errors or module records.

$datestringThe cut-off; records up to and **including** that date are gone.

Return 1

voidThe return is ignored.

Listener PHP

```php
Hook::add('action:admin.logs_cleared', 10, function ($type, $date) {
    // What is gone stays gone: note it in your own archive.
    Acme::noteRetention($type, $date);
});
```

### Following notification settings being saved

actionadmin.notification_settings_saved

`AdminSettings` template engine

Runs when the engine used for notification templates changes. That setting decides how **every** notification is produced.

Parameters 2

$enginestringThe chosen engine: none, Smarty or Twig.

$admin_idintThe administrator who changed it; zero when there is no session.

Return 1

voidThe return is ignored.

Listener PHP

```php
Hook::add('action:admin.notification_settings_saved', 10, function ($engine, $admin_id) {
    // Every notification is produced through this setting.
    Acme::notifyOps('notification engine: ' . $engine);
});
```

## Pitfalls

> **The id is unreliable when a privilege group is created**
> 
> On the create path the id in the privilege hook is **not the id of the new record** and may be zero. Tell a new record from the operation type. The department hook does not share this flaw; there the id is right on both paths.

> **The arrays carry what changed, not the whole record**
> 
> The arrays in the staff, profile and preference hooks hold only the **fields that changed**. A field being absent does not mean "removed", it means "untouched". Read the record separately if you need its current state.

## Related Articles

- [Management Panel Hooks](https://dev.wisecp.com/en/hooks-in-the-management-panel)
- [Customer Account Hooks](https://dev.wisecp.com/en/customer-account-hooks)
- [How Hooks Work](https://dev.wisecp.com/en/how-hooks-work)
