# Hizmet Modül Kancaları

https://dev.wisecp.com/tr/hizmet-modul-kancalari

Hizmeti gerçekten sağlayan modülle konuşan on kanca: çağrının önündeki kapılar, giden parametreler ve dönen sonuç.

## Genel Bakış

Sunucuda hesap açan, askıya alan, parola değiştiren kod **modüldedir**. Çekirdek yalnız "şu işi yap" der ve sonucu bekler.

Bu yolun **iki ayrı kapısı** vardır ve karıştırılmaları sık görülür: biri panelden gelen çağrılar için, diğeri müşterinin kendi panelinden gelenler için. Müşteri yolu daha dardır; modülün açıkça izin verdiği metotlar dışına çıkamaz.

## Referans

### Kurulacak hizmetin seçeneklerini değiştirme

filterservice.build_options

`Orders::buildServices()` siparişten hizmete

Sipariş kaleminden hizmet kurulurken, kayıt yazılmadan önce çalışır.

Parametreler 3

$service_dataarrayrefKurulacak hizmetin tam yükü: `type`, `product_id`, `amount`, `status`, `module`, `options`, `metrics`. `options` ve `metrics` dizi değil JSON metni olarak gelir: değiştirmeden önce çözün, sonra yeniden kodlayın.

$itemarrayKaynak sipariş kalemi. Değiştirilemez bağlam; müşterinin sipariş sırasında seçtikleri buradadır.

$productarrayÇözülmüş ürün satırı. Değiştirilemez bağlam.

Dönüş 1

voidDeğerler **referansla** değişir; dönüş kullanılmaz.

Dinleyici PHP

```php
Hook::add('filter:service.build_options', 10,
    function (&$service_data, $item, $product) {
        // options JSON olarak gelir: cozun, degistirin, yeniden kodlayin.
        $options = Utility::jdecode($service_data['options'] ?? '', true);
        if (!is_array($options)) $options = [];

        $options['acme_region'] = Acme::region($item);
        $service_data['options'] = Utility::jencode($options);
    });
```

### Modülün kurulacağı veriyi değiştirme

filterservice.module_context

`Hook::runRefs` modül nesnesi kurulmadan önce

`Services::run_module()` içinde, modül nesnesi kurulmadan hemen önce çalışır. Modül `$service['options']`'ı kurulum anında okur; bu yüzden bir değişikliğin sağlayıcıya ulaşabildiği son nokta burasıdır — aşağıdaki kapı bunun için artık geçtir.

Parametreler 3

$servicearrayrefHizmet kaydı. Modül nesnesi onun `options`'ından kurulur.

$actionstringrefÇalışacak işlem. Takma ad çözümü (`terminate` → `cancel`) bu kancadan sonra yapılır, yani yazdığınız yeni değer de çözülür.

$paramsarrayrefModül metoduna geçilecek argümanlar.

Dönüş 1

voidDeğerler **referansla** değişir; dönüş kullanılmaz.

Dinleyici PHP

```php
Hook::add('filter:service.module_context', 10,
    function (&$service, &$action, &$params) {
        if ($action !== 'create') return;

        // Modülün kurulacağı kopyaya yazılır; kayıtta da kalması gerekiyorsa
        // ayrıca kendiniz saklayın.
        $options = is_array($service['options'] ?? null) ? $service['options'] : [];
        $options['ip'] = Acme::reserve((int) $service['id']);
        $service['options'] = $options;
    });
```

> **Her create yolu buradan, yalnız buradan geçer**
> 
> Yükseltme/düşürmenin yeniden kurma yolu `run_module()`'e **hazır bir dizi** verir ve kaydı yeniden okumaz. Yalnız `action:service.created`'ı dinleyen bir listener o yolu kaçırır; hizmet, listener'ın eklemek istediği şey olmadan kurulur.

### Modül işlemini durdurma

gateservice.module_action

`Services::run_module()` panel yolu

Modül metodu çağrılmadan önce çalışır. Bu kapı **panelden** gelen çağrılar içindir.

Parametreler 3

$servicearrayHizmet kaydı.

$actionstringÇalışacak işlem: `create`, `suspend`, `cancel` ve benzerleri.

$paramsarrayModül metoduna gidecek parametreler.

Dönüş 1

stringBoş olmayan bir string işlemi **durdurur**; metin hata olarak fırlatılır ve modül çağrılmaz.

Dinleyici PHP

```php
Hook::add('gate:service.module_action', 10, function ($service, $action, $params) {
    // Bakim penceresinde sunucuya yazma islemi gondermeyin.
    if (in_array($action, ['create', 'suspend', 'cancel'], true)
        && Acme::maintenance((int) ($service['server_id'] ?? 0)))
        return 'Sunucu bakimda; islem simdi yapilamaz.';

    return null;
});
```

### Modül çağrısını izleme

actionservice.module_ran

`Services::run_module()` tek dizi parametre

Modül metodu koştuktan sonra çalışır — **başarılı olsun ya da olmasın**.

Parametreler 1

$payloadarrayTek bir dizi taşır: `service`, `instance` (modül örneği), `action`, `result`, `error`. Diğer kancaların aksine parametreler **ayrı ayrı gelmez**; hepsi bu dizinin içindedir.

Dönüş 1

voidDönüş yoksayılır.

Dinleyici PHP

```php
Hook::add('action:service.module_ran', 10, function ($payload) {
    // TEK parametre gelir; icindeki error alani basarisizligi soyler.
    if (!empty($payload['error']))
        Ops::alert('module-failed', $payload['action'] ?? '', $payload['error']);
});
```

### Modülün sonucunu değiştirme

filterservice.module_result

`Hook::runRefs` beş argüman da referans

Modül dönüşü çekirdeğe işlenmeden önce çalışır. **Beş argümanın hepsi** referansla gelir.

Parametreler 5

$servicearrayrefHizmet kaydı.

$instanceobjectrefModül örneği.

$actionstringrefÇalıştırılan işlem.

$resultmixedrefModülün dönüşü: yapılandırma dizisi, giriş bilgisi, `false` ya da başka bir değer. Asıl değiştireceğiniz alan budur.

$errormixedrefHata mesajı ya da `null`. Buraya yazmak çekirdeğe "bu iş düştü" demektir.

Dönüş 1

voidDeğerler **referansla** değişir; dönüş kullanılmaz.

Dinleyici PHP

```php
Hook::add('filter:service.module_result', 10,
    // Varsayılanlar ZORUNLU: modül başarılı olduğunda $error null gelir, null bir argüman
    // düşürülür ve beş zorunlu parametreli bir listener başarılı çağrıda hiç çalışmaz.
    function (&$service = null, &$instance = null, &$action = null, &$result = null, &$error = null) {
        // Saglayicinin gecici hatasini yeniden denenebilir hale getirin.
        if ($error && Acme::transient((string) $error)) {
            $error  = null;
            $result = false;          // cekirdek 'basarisiz' der, alarm uretmez
        }
    });
```

### Müşteri panelinden gelen çağrıyı durdurma

gateservice.client_tool

`ClientServices` müşteri yolu

Müşteri kendi panelinden bir modül işlemi çağırdığında çalışır. Bu kapı panel kapısından **ayrıdır**.

Parametreler 3

$servicearrayMüşterinin kendi hizmeti.

$methodNamestringÇağrılacak gerçek modül metodu: doğrudan çağrılabilir bir ad (`sso_panel_login`) ya da `handle_` önekli biçim.

$moduleobjectModül örneği. Müşteri kipinde kurulmuştur; panel-only satırlar zaten düşmüştür.

Dönüş 1

stringBoş olmayan bir string çağrıyı **durdurur**; müşteriye hata olarak döner.

Dinleyici PHP

```php
Hook::add('gate:service.client_tool', 10, function ($service, $methodName, $module) {
    // Panele tek tikla giris hassastir: dogrulanmamis hesaba kapatin.
    if ($methodName === 'sso_panel_login' && !Acme::verified($service))
        return 'Panele giris icin once hesabinizi dogrulayin.';

    return null;
});
```

### Müşteri çağrısını izleme

actionservice.client_tool_ran

`ClientServices` iki ayrı metot adı

Müşterinin çağırdığı modül metodu koştuktan sonra çalışır.

Parametreler 4

$servicearrayHizmet kaydı.

$methodstring**İstek seviyesindeki** ad: `tool_action`, `tool_table`, `sso_panel_login` ya da modülün açtığı bir anahtar.

$methodNamestring**Fiilen çağrılan** modül metodu. İkisi çoğu zaman farklıdır; hangisine baktığınıza dikkat edin.

$moduleResultmixedModülün dönüş değeri. Modülün doğrudan yazdırdığı çıktı **buraya girmez**.

Dönüş 1

voidDönüş yoksayılır.

Dinleyici PHP

```php
Hook::add('action:service.client_tool_ran', 10,
    function ($service, $method, $methodName, $moduleResult) {
        // Istek adi ile gercek metot farklidir: denetim kaydina IKISINI de yazin.
        Audit::clientTool((int) ($service['id'] ?? 0), $method, $methodName);
    });
```

### Yapılandırma alanlarını değiştirme

filterservice.config_fields

`Hook::runRefs` alanlar ve işlemler

Modülün sunduğu yapılandırma ekranı hazırlandıktan sonra çalışır.

Parametreler 2

$configarrayrefİki anahtar taşır: `actions` ve `fields`. Alan ekleyebilir, çıkarabilir ya da değiştirilemez yapabilirsiniz.

$moduleServerModuleHizmetin modül örneği.

Dönüş 1

voidDeğerler **referansla** değişir; dönüş kullanılmaz.

Dinleyici PHP

```php
Hook::add('filter:service.config_fields', 10, function (&$config, $module) {
    // Tehlikeli islemi operator disinda kimseye gostermeyin.
    unset($config['actions']['rebuild']);
});
```

### Hizmet parolası değişimini izleme

actionservice.password_changed

`ClientServices` parola taşınmaz

Hizmetin panel parolası değiştikten sonra çalışır.

Parametreler 2

$servicearrayParolası değişen hizmet.

$uidintHizmet sahibinin hesap kimliği.

Dönüş 1

voidDönüş yoksayılır.

Dinleyici PHP

```php
Hook::add('action:service.password_changed', 10, function ($service, $uid) {
    // Yeni parola kancaya GELMEZ; yalniz degistigini bildirin.
    Notify::securityEvent($uid, 'service-password', (int) ($service['id'] ?? 0));
});
```

### Sunucu değişimini izleme

actionservice.server_changed

`AdminServices` taşıma sonrası

Bir hizmet başka sunucuya atandıktan sonra çalışır. Kayıt taşınmıştır ama **veriyi kimse taşımaz**: bu kanca taşımayı sizin başlatmanız içindir.

Parametreler 4

$idintHizmetin kimliği.

$currentServerIdintÖnceki sunucu; **sıfır** ise hizmetin sunucusu yoktu.

$new_server_idintYeni sunucu; **sıfır** ise sunucudan çıkarılmıştır.

$newServerTypestringHizmete atanan yeni modül tipi.

Dönüş 1

voidDönüş yoksayılır.

Dinleyici PHP

```php
Hook::add('action:service.server_changed', 10,
    function ($id, $currentServerId, $new_server_id, $newServerType) {
        // Kayit tasindi, veri tasinmadi: tasimayi siz baslatin.
        if ($currentServerId && $new_server_id)
            Acme::queueMigration($id, $currentServerId, $new_server_id);
    });
```

## Tuzaklar

> **İki kapı vardır ve biri diğerini kapsamaz**
> 
> Panelden gelen çağrılar bir kapıdan, müşteri panelinden gelenler **başka** bir kapıdan geçer. Yalnız birine bağlanan bir kural, öbür yoldan **atlanabilir**. Kuralınız her iki taraf için geçerliyse ikisine birden bağlanın.

> **Modül olayı tek dizi taşır**
> 
> Diğer kancalar parametreleri ayrı ayrı verirken modül çalıştı kancası **tek bir dizi** verir. Dört parametre bekleyen bir dinleyici, kanca iki değer fırlatmadığı için değil, **bir** fırlattığı için düşer. İçindeki hata alanını okumak da başarıyı anlamanın tek yoludur.

> **Sonuç filtresi hatayı da yazabilir**
> 
> Sonuç filtresinde **beş argüman da** referanslıdır: sonucu *ve* hata alanını değiştirebilirsiniz. Hata alanını temizlemek çekirdeğe "bu iş düşmedi" demektir; yanlış kullanıldığında **gerçek bir başarısızlık gizlenir** ve kimse fark etmez.

> **Müşteri yolu zaten dardır**
> 
> Müşteri panelinden yalnız modülün **açıkça izin verdiği** metotlar çağrılabilir; kurma, sonlandırma ve askıya alma oraya hiç ulaşmaz. Kapıya ek kural yazmadan önce buna bakın: engellemeye çalıştığınız şey **zaten** kapalı olabilir.

## İlgili Makaleler

- [Hizmet Durum Kancaları](https://dev.wisecp.com/tr/hizmet-durum-kancalari)
- Modül Yaşam Döngüsü Kancaları
- [Hizmet Yaşam Döngüsü Kancaları](https://dev.wisecp.com/tr/hizmet-yasam-dongusu-kancalari)
