# Panel Service Screen Hooks

https://dev.wisecp.com/es/admin-service-screen-hooks

The eighteen placement points of the service screens: the detail tabs, the title area and the toolbars of the side lists.

## Overview

The placement points of the service screens live here. They cover every tab of the detail page, the title area and the toolbars of the side lists.

Most detail points hand you the service record. Some add something that **can arrive empty**: the product record when the product was gone, or the module instance when the service has no server. Test before reaching into those.

## Reference

### A badge or button in the service title

uiadmin.service_detail.header_actions

`admin/services/detail` the title area

Appears in the title row of the service detail. Put the state on the remote panel or a shortcut of your own here.

Parameters 1

$servicearrayThe active service record.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.service_detail.header_actions', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### A new tab on the service detail

uiadmin.service_detail.tabs

`admin/services/detail` an object, not an array

Runs once the core tabs are built. You do not return HTML: you add the tab through the object’s method. Two flags tell you which tab makes sense.

Parameters 4

$tabobjectThe tab object.

$servicearrayThe full service record.

$is_domainboolWhether the service is a domain. Server tabs make no sense on a domain; decide from this.

$has_moduleboolWhether the service sits on a server. A false here leaves a tab pulling remote data empty.

Return 1

voidThe return is **not used**. This point shows no HTML: the tab is added through the object’s method.

Listener PHP

```php
Hook::add('ui:admin.service_detail.tabs', 10,
    function ($tab, $service, $is_domain, $has_module) {
        // Sunucusu olmayan hizmette uzak panel sekmesi bos cikar.
        if (!$has_module) return;

        $tab->add('acme', 'Acme', Acme::renderTab((int) ($service['id'] ?? 0)));
    });
```

### The bottom of the details tab

uiadmin.service_detail.details.bottom

`admin/services/detail` the product may be empty

Appears below the service details.

Parameters 2

$servicearrayThe active service record.

$productarrayThe product behind the service. It **arrives empty** when the product was deleted or the service is not tied to one.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.service_detail.details.bottom', 10, function ($service, $product) {
    // Urun BOS gelebilir.
    if (!$product) return null;

    return '<div class="mt-3">' . htmlspecialchars(Acme::planNote($product)) . '</div>';
});
```

### The bottom of the management tab

uiadmin.service_detail.management.bottom

`admin/services/detail` the module may be empty

Appears below the server management tools.

Parameters 2

$servicearrayThe active service record.

$moduleobjectThe loaded server module. ? It **can arrive empty** when the service has no server or the module failed to load. Test before calling a method.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.service_detail.management.bottom', 10, function ($service, $module) {
    // Modul BOS gelebilir: metot cagirmadan once sinayin.
    if (!$module) return null;

    return Acme::renderRemotePanel($module, $service);
});
```

### The top of the add-ons tab

uiadmin.service_detail.addons.top

`admin/services/detail` top of the tab

Appears above the list of service add-ons.

Parameters 1

$servicearrayThe active service record.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.service_detail.addons.top', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### The bottom of the requirements tab

uiadmin.service_detail.requirements.bottom

`admin/services/detail` the filled answers

Appears below the details asked of the customer during the order.

Parameters 2

$servicearrayThe active service record.

$requirementsarrayThe requirements filled in for this service.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.service_detail.requirements.bottom', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### The bottom of the history tab

uiadmin.service_detail.history.bottom

`admin/services/detail` below the history

Appears below the service history. The place to put your own record beside the core one.

Parameters 1

$servicearrayThe active service record.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.service_detail.history.bottom', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### The top of the package change tab

uiadmin.service_detail.upgrade.top

`admin/services/detail` the remainder in hand

Appears above the package upgrade screen. The remaining days and amount are in your hands, so you can show your own pricing note here.

Parameters 3

$servicearrayThe active service record.

$productarrayThe current product record.

$remainingarrayThe remainder: days used, days left and the amount left.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.service_detail.upgrade.top', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### The bottom of the transfer tab

uiadmin.service_detail.transfer.bottom

`admin/services/detail` carries a secret

Appears below the domain transfer screen.

Parameters 2

$servicearrayThe active domain record.

$service_optionsarrayThe service options: the transfer lock and the **authorisation code**. ? That code is a secret: keep it off the screen and out of your records.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.service_detail.transfer.bottom', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### The bottom of the verification tab

uiadmin.service_detail.verification.bottom

`admin/services/detail` domain verification

Appears below the domain contact verification screen.

Parameters 2

$servicearrayThe active domain record.

$service_idintThe service id.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.service_detail.verification.bottom', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### The very bottom of the service page

uiadmin.service_detail.bottom

`admin/services/detail` end of the page

Appears at the very end of the page. It suits a panel that belongs to no tab.

Parameters 1

$servicearrayThe service record on screen.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.service_detail.bottom', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### The service list toolbar

uiadmin.service_list.toolbar

`admin/services` no parameters

Appears in the button group above the service list.

Parameters 0

—It takes no parameters.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.service_list.toolbar', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### Above the table on the service list

uiadmin.service_list.before_table

`admin/services` no parameters

Appears immediately above the service table.

Parameters 0

—It takes no parameters.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.service_list.before_table', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### The add-on list toolbar

uiadmin.service_addon_list.toolbar

`admin/services` no parameters

Appears in the toolbar of the service add-on list.

Parameters 0

—It takes no parameters.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.service_addon_list.toolbar', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### Above the table on the add-on list

uiadmin.service_addon_list.before_table

`admin/services` no parameters

Appears immediately above the add-on table.

Parameters 0

—It takes no parameters.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.service_addon_list.before_table', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### The cancellation request toolbar

uiadmin.service_cancellation_list.toolbar

`admin/services` no parameters

Appears in the toolbar of the cancellation request list.

Parameters 0

—It takes no parameters.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.service_cancellation_list.toolbar', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### The transfer list toolbar

uiadmin.service_transfer_list.toolbar

`admin/services` no parameters

Appears in the toolbar of the service transfer list.

Parameters 0

—It takes no parameters.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.service_transfer_list.toolbar', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### The package change list toolbar

uiadmin.service_updowngrade_list.toolbar

`admin/services` no parameters

Appears in the toolbar of the package upgrade and downgrade list.

Parameters 0

—It takes no parameters.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.service_updowngrade_list.toolbar', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

## Pitfalls

> **The module instance can be empty**
> 
> The module parameter on the management tab is **empty** when the service has no server or the module failed to load. A listener calling a method straight away raises a fatal error there and takes **the whole page** down: it is not your panel that breaks but the administrator’s service screen.

> **The transfer point carries the authorisation code**
> 
> The options array on the transfer tab holds the **authorisation code** of the domain. Whoever sees that code can move the domain to another registrar: keep it off the screen, out of your logs and away from outside services.

## Related Articles

- [Panel Screen Data Hooks](https://dev.wisecp.com/en/admin-screen-data-hooks)
- [Service Hooks](https://dev.wisecp.com/en/service-lifecycle-hooks)
- [Management Panel Hooks](https://dev.wisecp.com/en/hooks-in-the-management-panel)
