# Module Settings and Data Hooks

https://dev.wisecp.com/es/module-settings-hooks

The nine hooks over module settings, the API record, tool data and imports.

## Overview

Module settings are saved from four separate places: the module’s own settings, add-on settings, the settings on a page the module opened, and fraud check settings. Each raises its own event.

Beside them sit three filters over data: tool data, the import archive and the transferable types. And one record fires after every outside call.

## Reference

### Following module settings being saved

actionmodule.config_saved

`AdminModules` after the write

Runs after the settings of a module are saved.

Parameters 2

$typestringThe module type.

$keystringThe module key.

Return 1

voidThe return is ignored.

Listener PHP

```php
Hook::add('action:module.config_saved', 10, function ($type, $key) {
    Acme::invalidateModuleCache($type, $key);
});
```

### Following add-on settings being saved

actionmodule.addon_settings_saved

`AddonModule` carries secrets

Runs after the settings of an add-on are saved.

Parameters 2

$namestringThe key of the add-on.

$configarrayThe whole configuration written to disk. It holds API keys and access settings: keep it out of your own records and your logs.

Return 1

voidThe return is ignored.

Listener PHP

```php
Hook::add('action:module.addon_settings_saved', 10, function ($name, $config) {
    // Do not carry the configuration itself.
    Acme::notifyOps('add-on settings changed: ' . $name);
});
```

### Following module area settings being saved

actionmodule.area_settings_saved

`AdminArea` only what was sent

Runs after settings on the module’s own management page are saved.

Parameters 3

$module_typestringThe module type.

$module_namestringThe module name.

$valuesarrayThe saved values. Only **what this call sent** is here, not the full settings. Do not read a missing key as "removed".

Return 1

voidThe return is ignored.

Listener PHP

```php
Hook::add('action:module.area_settings_saved', 10,
    function ($module_type, $module_name, $values) {
        // The array holds what was SENT, not the whole settings.
        Acme::auditChange($module_name, array_keys($values));
    });
```

### Following fraud module settings

actionmodule.fraud_settings_saved

`FraudModule` carries secrets

Runs after the settings of a fraud check module are saved.

Parameters 2

$namestringThe module key.

$configarrayThe configuration written: its status and settings. It holds a service key; do not carry it.

Return 1

voidThe return is ignored.

Listener PHP

```php
Hook::add('action:module.fraud_settings_saved', 10, function ($name, $config) {
    Acme::notifyOps('fraud check settings changed: ' . $name);
});
```

### Following a module API record

actionmodule.api_logged

`ModuleBase` raw request and response

Runs after a module talks to an outside service. It fires for **every** call, so this is a busy path.

Parameters 4

$typestringThe module type.

$modulestringThe module name.

$actionstringThe operation recorded.

$log_dataarrayThe whole record: the request sent, the response received and the request details. ? It holds **server passwords, API keys and customer data** in the clear. Pick out what you actually need before copying it anywhere.

Return 1

voidThe return is ignored.

Listener PHP

```php
Hook::add('action:module.api_logged', 10, function ($type, $module, $action, $log_data) {
    // Do NOT copy the whole record: it carries secrets.
    Acme::metric($type . '.' . $module . '.' . $action);
});
```

### Changing tool data

filtermodule.tool_data

`ServerModule` passed by link

Runs after a server tool returns its data and before it reaches the screen: mailboxes, databases and their siblings.

Parameters 3

$toolstringThe tool key.

$actionstringThe tool operation; the default is the list view.

$dataarrayby linkThe data returned by the module, already normalised.

Return 1

voidThe return is ignored; you write over the data. The hook fires for every tool: check which one you are in first.

Listener PHP

```php
Hook::add('filter:module.tool_data', 10, function ($tool, $action, &$data) {
    // The hook fires for every tool.
    if ($tool !== 'databases') return;

    $data = Acme::hideSystemDatabases($data);
});
```

### Stopping an import

gatemodule.import_run

`Imports` the reset mode

Runs before a transfer from another system begins. One of the modes **wipes the existing data**, which makes a check here worth the most.

Parameters 3

$platformstringThe source platform.

$typestringThe type of data to transfer.

$import_typestringThe mode: `clean` **wipes** what is there, `enrich` adds to it.

Return 1

string|null**A non-empty text blocks the operation** and is shown as the error. An empty return lets it carry on.

Listener PHP

```php
Hook::add('gate:module.import_run', 10, function ($platform, $type, $import_type) {
    // 'clean' WIPES what is there: close it on live data.
    if ($import_type === 'clean' && Acme::hasLiveData($type))
        return 'A wiping import cannot run over live data.';

    return null;
});
```

### Changing which archive is opened

filtermodule.import_archive

`AdminModules` passed by link

Runs before an uploaded module archive is opened. Change the path and **a different file** is opened.

Parameters 2

$theFilestringby linkThe full path of the archive in the temporary folder. What you write over it is what gets opened.

$groupstringThe target module type.

Return 1

voidThe return is ignored; you write over the path. If you put a file of your own here, make sure the path is under your control.

Listener PHP

```php
Hook::add('filter:module.import_archive', 10, function (&$theFile, $group) {
    // Changing the path opens ANOTHER file: hand over one you built.
    $theFile = Acme::repackage($theFile, $group);
});
```

### Changing which data types can transfer

filtermodule.import_data_types

`Imports` passed by link

Runs while the import wizard asks which data types it should offer.

Parameters 2

$data_typesarrayby linkThe type list; each carries a name, a description and whether it is required.

$platformstringThe active platform.

Return 1

voidThe return is ignored; you write over the list. Dropping a type marked required can start the transfer with data missing.

Listener PHP

```php
Hook::add('filter:module.import_data_types', 10, function (&$data_types, $platform) {
    // Dropping a required type starts the transfer short.
    $data_types['acme-notes'] = [
        'name'        => 'Acme notes',
        'description' => 'Notes attached to customer records',
        'required'    => false,
    ];
});
```

## Pitfalls

> **The API record carries raw secrets**
> 
> The record holds the request sent to the outside service and the response as they were: **server passwords, API keys, customer data**. Copying that array into your own store spreads those secrets to a second place. Pick the field you need; do not carry the whole thing.

> **A wiping import cannot be undone**
> 
> One import mode **deletes** the data already there. The import gate is the only place you can keep that mode away from live data.

## Related Articles

- Module Hooks
- [System Event Hooks](https://dev.wisecp.com/en/system-event-hooks)
- [How Hooks Work](https://dev.wisecp.com/en/how-hooks-work)
