Sunucu Modülü Araçları
Araçlar, müşterinin hizmetin içinde gördüğü sayfalardır: dosya yöneticisi, veritabanları, DNS, zamanlanmış görevler. Etrafındaki her şeyi taban sınıf üstlenir; siz iki metot ve bir şablon verirsiniz.
Genel Bakış
ServerModule, gruplanmış ve sıralanmış bir araç tanımı kataloğu taşır; hepsi kapalı gelir. Birini açmak, onu desteklenir ilan etmek ve iki soruyu yanıtlamak demektir: sayfa neyi gösteriyor ve buton ne yapıyor.
Tarayıcı ile o iki yanıt arasındaki her şey taban sınıfa aittir.
tool_data() metodunuzu çağırır, satırları normalleştirir, filtre kancasını çalıştırır, istek başına önbelleğe alır.
tool_action() metodunuzu çağırır, sırları maskeleyerek hizmet geçmişine yazar.
Ön Koşullar
- Çalışan bir sunucu modülü (Sunucu Modülü Yazma). Araçlar ancak
create()hesap kimliğini sakladıktan sonra açılır. - Ana varlığın canlı sağlayıcıda hem oluşturmayı hem silmeyi desteklediğini doğrulayın.
- Sağlayıcının ücretlendirdiği bir şey oluşturuluyorsa önce kotayı planlayın.
Yapı
Altı katman, üçü sizin.
| Katman | Nerede | Ne tutar |
|---|---|---|
| Katalog | coremio/classes/ServerModule.php | Tanım, filtreler, kurallar, kolonlar, satır geri çağrıları |
| Aracı açma | config.php ya da configure_features() | Desteklenen araçlar ve yetenekleri |
| Okuma | Modülünüz, tool_data() | Araç başına bir dal, sonra bir fetch metodu |
| Yazma | Modülünüz, tool_action() | Araç başına bir dal, sonra bir aksiyon yönlendiricisi |
| Arayüz | templates/system/module/service/hosting/tools | Araç adı başına paylaşılan şablon |
| Metin | coremio/locale/en/cm/system/module.php | Paylaşılan etiketler ve mesajlar |
Adım Adım
Aracı Açın
Adı yapılandırmada bildirmek aracı varsayılan yetenekleriyle açar.
// config.php: bildirimsel yarı.
return [
// ... modül yapılandırmasının geri kalanı
'supported' => [
'tools' => ['file-manager', 'ftp-accounts', 'databases', 'cron-jobs'],
// Araç başına seçenek ezmeleri; set_tool() metodunun yazacağı anahtarların aynısı.
'tool_options' => [
'file-manager' => ['allow_upload_overwrite' => true, 'allow_chmod_recursive' => true],
],
],
];
public function configure_features(): void
{
// Yapılandırma listesiyle aynı etki; karar canlı duruma bağlı olduğunda işe yarar.
$this->support_tools(['cron-jobs' => ['list', 'create', 'delete']]);
// Sağlayıcıda hesap başına kota ve zamanlanmış görevlerde e-posta alanı yok,
// bu yüzden karşılayamadığımız yetenekleri ve besledikleri kolonu kaldırın.
$this->remove_tool_capability('ftp-accounts', ['quota']);
$this->remove_tool_column('ftp-accounts', ['quota']);
$this->set_tool_order('databases', 5);
}
Okuma Yolu
tool_data() tek bir dağıtıcıdır; araca özgü işi özel fetch metotlarında tutun.
['items' => [...]]döndürün; her satır kolon adıyla anahtarlanır, yanına şablonun okuduğu ek anahtarları koyun.
Yazma Yolu
tool_action() aynı biçimdedir; aksiyon fiiline göre eşleştiren bir yönlendiriciye dağıtır.
- Sağlayıcı reddederse fırlatın; mesaj müşteriye kırmızı uyarı olarak ulaşır.
[]döndürün ya da arayüz bir değer bekliyorsa bir yük döndürün.
Kolonlar ve Metin
Kolon başlıkları, etiketler ve başarı mesajları paylaşılan dil dosyasından gelir. Şablon paylaşılır, yani bir alan adı sözleşmedir. Sağlayıcıya özgü dizeler kendi modül dil dosyanızda durur.
Etkinlik günlüğü her işlemi activity_action_label() ile adlandırır: taban sınıf yaygın sanal sunucu işlemleri için system/module/al-action/{kod} anahtarına bakar, bulamazsa kodu okunur biçimde gösterir. Kodun kendisi süzgeç değeri olarak kalır. Sağlayıcınız kendi işlem adlarını kullanıyorsa metodu ezip etiketleri modül dil dosyanızdan döndürün.
Referans
Araç Tanımı
$this->tools['ftp-accounts'] = [
'name' => 'FTP Accounts',
// Grup adları config.php'de bildirilen modül tipine bağlıdır:
// hosting: files, databases, domains, email, software, security
// server: power, system, network, storage
'group' => 'files',
'order' => 20, // grup içindeki konum
'icon' => 'bi bi-hdd-network', // bir Bootstrap simgesi ya da uzak bir görsel için 'img:<url>'
'page' => 'ftp-accounts', // tools/ altındaki şablon dosyasının adı
'type' => 'page-loader', // 'page-loader' bir sayfa basar, 'action' tek bir düğmedir
'supported' => false, // modülünüz bunu açar
'capabilities' => ['list', 'create', 'edit', 'delete', 'quota', 'directory'],
];
false gelir. Desteklenmeyen bir araca gelen istek, kodunuz çalışmadan reddedilir.
'page-loader', page ile adlandırılan şablonu yükler; 'action' araç ızgarasındaki tek butondur, isteğe bağlı 'confirm' => true ile.
get_content ve save_content edit sayılır; update_email ise email sayılır.
Modül İmzaları
// Taban sınıfın çağırdığı iki metot. $params temizlenmiş sorgu parametrelerini,
// $data ise temizlenmiş POST gövdesini taşır.
public function tool_data(string $tool, string $action = 'index', array $params = []): array;
public function tool_action(string $tool, string $action, array $data = []): array;
// İsteğe bağlı: kataloğu bu modüle göre düzenler. Sunucu kaydı bağlandığında
// (yapıcıdan, set_server üzerinden) ve bir kez de set_service içinden koşar.
public function configure_features(): void;
// İsteğe bağlı: yalnız parola sıfırlama aracının parolayı panele ürettirmesi gerektiğinde.
protected function panel_generated_password(): string;
Taban Sınıf Yardımcıları
public function support_tools(array $tools): static;
public function add_tool(string $key, array $config): static;
public function set_tool(string $key, array $config): static;
public function remove_tool(string $key): static;
public function set_tool_order(string $key, int $order): static;
public function add_tool_capability(string $key, array|string $capabilities): static;
public function remove_tool_capability(string $key, array|string $capabilities): static;
public function add_tool_column(string $tool, string $column, array $config): static;
public function remove_tool_column(string $tool, array|string $columns): static;
public function add_tool_group(string $key, array $config): static;
public function set_tool_group_order(string $key, int $order): static;
public function get_tool(string $key): ?array;
public function get_tools(): array;
public function get_effective_tools(): array;
public function get_disabled_features(): array;
public function has_client_management(): bool;
Düz bir liste elemanı aracı varsayılan yetenekleriyle açar. Bir diziye işaret eden anahtar ise o listeyi geçtiğinizle değiştirir.
Doğrulama Katmanları
Üçü de taban sınıfta bildirilir ve aksiyon metodunuzdan önce çalışır.
// 1. Temizleme. Listede olmayan her alan 'hclear' filtresine düşer.
protected function get_tool_action_data_filters(): array;
// Bu araç için ürünle gelen kural, birebir. FTP kullanıcı adının e-posta gibi
// filtrelendiğine dikkat edin: paneller user@domain biçimini kabul eder.
// 'ftp-accounts' => ['username' => 'email', 'password' => null,
// 'directory' => 'path', 'quota' => 'numeric']
// Filtreler: hclear, numeric, route, identifier, domain, subdomain, hostname,
// email, email_list, ip, url, path, json_filenames, null (dokunmadan geçer)
// 2. Aksiyon başına zorunlu alanlar. Kırpma sonrası boş dize fırlatır.
protected function get_tool_action_rules(): array;
// 'ftp-accounts' => ['create' => ['username', 'password'],
// 'edit' => ['username'], 'delete' => ['username']]
// 3. Biçim denetimleri; zorunluluk denetiminden sonra koşar (işlemin zorunlu alanı
// olmasa da), boş değerlerde atlanır.
protected function get_tool_action_field_validations(): array;
// 'mx-entry' => ['create' => ['domain' => ['domain'], 'priority' => ['numeric']]]
// Kurallar: url, email, email_list, email_local, ip, ipv4, ipv6, ip_or_wildcard,
// domain, dns_label, dns_name, numeric, cron_field, enum:a,b,c, min:N, max:N
// Tanınmayan kural adı atlanır ve hata kütüğüne uyarı olarak yazılır.
Diğer her filtre parolayı güçlü kılan karakterleri siler: hesap, müşterinin yazmadığı bir sırla açılır.
tool_action() Dönüşleri
action-success-{tool}-{action}, sonra action-success-{action}, sonra üretilmiş bir etiket arar.
Şablon Değişkenleri
/** @var ServerModule $module canlı örnek, yani $module->service erişilebilir */
/** @var string $tool slug */
/** @var array $tool_config tanım; yetenekler ve seçenekler dahil */
/** @var string $tool_label çevrilmiş araç adı */
/** @var string $action sayfa bir alt aksiyonla açılmadıysa 'index' */
/** @var array $data fetch metodunuzun döndürdüğünün aynısı */
/** @var mixed $table hazırlanmış listeleme tablosu, aracın kolonu yoksa null */
/** @var array $tables alt tablolar, kendi slug'larıyla anahtarlanır */
/** @var bool $admin_view admin panelde true, müşteri panelinde false */
/** @var string|null $error fetch başarısız olduğunda dolar */
| Tarayıcı fonksiyonu | Amacı |
|---|---|
request_tool_action(tool, action, data, options) | Tek bir aksiyonu gönderir, buton göstergesi ve bildirimle |
reload_module_content(tool) | Araç sayfasını değişiklikten sonra yeniden yükler |
open_modal(id, {title, body, footer}) | Bir pencere kurar ve açar |
confirmDeleteModal({message, description, buttonText, onConfirm}) | Standart silme onayı |
watchRequired(selector) | Zorunlu alanlar dolunca gönderi etkinleştirir |
passwordInput(id, placeholder, options) | Üret, göster ve kopyala butonlu parola alanı |
Örnek
Baştan sona tek bir araç: okuma, yönlendirici ve taban sınıf.
public function tool_data(string $tool, string $action = 'index', array $params = []): array
{
$username = $this->options['config']['user'] ?? '';
$domain = $this->options['domain'] ?? '';
return match ($tool) {
'ftp-accounts' => $this->fetch_ftp_accounts($username, $domain),
'databases' => $this->fetch_databases($username),
default => [],
};
}
private function fetch_ftp_accounts(string $username, string $domain): array
{
$response = $this->api->call('ftp/list', ['username' => $username]);
$items = [];
foreach ($response['data'] ?? [] as $row)
$items[] = [
'username' => $row['user'] ?? '',
'directory' => $row['dir'] ?? '/',
'quota' => (int) ($row['quota'] ?? 0),
];
// 'items' tabloyu besler; geri kalan her şeyi şablon okur.
return ['items' => $items, 'domain' => $domain];
}
public function tool_action(string $tool, string $action, array $data = []): array
{
$username = $this->options['config']['user'] ?? '';
return match ($tool) {
'ftp-accounts' => $this->action_ftp_accounts($action, $data, $username),
default => throw new Exception($this->lang['err-tool-unknown']),
};
}
private function action_ftp_accounts(string $action, array $data, string $username): array
{
return match ($action) {
'create' => $this->ftp_create($data, $username),
'delete' => $this->ftp_delete($data, $username),
default => throw new Exception($this->lang['err-action-unknown']),
};
}
private function ftp_create(array $data, string $username): array
{
$this->api->call('ftp/create', [
'account' => $username,
// Bildirilen filtrelerle zaten temizlendi ve varlığı zaten denetlendi.
'user' => $data['username'] ?? '',
'password' => $data['password'] ?? '',
'directory' => $data['directory'] ?? '/',
], 'POST');
// Boş dizi: çevrilmiş başarı mesajını taban sınıf yazar.
return [];
}
// ServerModule::handle_tool_action, önemli olan sıraya indirgenmiş hali.
$tool = Filter::init("REQUEST/tool", "route");
$action = Filter::init("REQUEST/action", "route") ?: 'index';
$data = !empty($_POST) ? $_POST : $_GET;
unset($data['operation'], $data['method'], $data['tool'], $data['action']);
$data = $this->sanitize_tool_action_data($tool, $data);
$tool_config = $this->get_tool($tool);
if (!$tool_config) throw new \Exception('Tool not found');
if (empty($tool_config['supported'])) throw new \Exception('Tool not supported');
$this->check_tool_capability($tool_config, $action);
$this->validate_tool_action($tool, $action, $data);
$result = $this->tool_action($tool, $action, $data);
// Aksiyon hizmet geçmişine ulaşmadan önce sırlar maskelenir.
foreach ($data as $k => $v)
if (is_string($v) && $v !== '' && preg_match('/pass(word)?|secret|token/i', (string) $k))
$data[$k] = '***';
if (empty($result)) return $this->tool_action_success_response($tool, $action);
return $result;
var TOOL = 'ftp-accounts';
window.ftpCreateSubmit = function (btn) {
request_tool_action(TOOL, 'create', {
username: document.getElementById('ftpUser').value,
password: document.getElementById('ftpPass').value,
directory: document.getElementById('ftpDir').value,
}, {
button: btn,
buttonLoader: creating_loader,
successToast: true,
afterDone: function () {
close_modal(document.querySelector('.modal.show'));
reload_module_content(TOOL);
},
});
};
Tuzaklar
Arayüz her varsayılan yetenek için bir denetim gösterir. Yönlendiricinizin karşılamadığını kaldırın, yoksa müşteri Düzenle'ye tıklar ve "Action not available" alır.
Açık bir oluştur butonu merakı sizin faturanıza dönüştürür. Kaynağı bir eklentiye bağlayın ve hak tükendiğinde aksiyonu reddedin.
Tarayıcı yardımcısı gövdeyi araç aksiyonuyla kurar, sonra verinizi üzerine birleştirir. action adlı bir alan fiili ezer ve dağıtıcı hata fırlatır. Ön ek verin (task_action) ve adı şablonda, zorunlu alan kurallarında ve aksiyon metodunuzda değiştirin.
Yardımcı o anahtarı aynı sekmede, geri çağrınız bitmeden işler. Bir pencerede ya da yeni sekmede açmak istediğiniz URL için console_url gibi nötr bir ad kullanın.
Sağlayıcı aracın ana varlığını hem oluşturamıyor hem silemiyorsa araç yayınlanmaz. Yapılandırmadan çıkarın ve ölü metotları silin.
Müşterinin Yönetim sekmesi yalnız has_client_management() true iken açılır: en az bir etkin araç ya da müşteri alanında kalan bir kart. Göstergeler, hesap bilgisi, kaynaklar ve bağlantılar Genel Bakış sekmesinde durduğu için sayılmaz. Çekirdek bu soruyu operatörün kısıtlamaları uygulanmış hâlde sorar; Tercihler'de her aracı gizlemek de sekmeyi kaldırır. Yalnız tek tıkla giriş sunan bir panelin başlatıcısı Hızlı İşlemler'de kalır.
İlgili Makaleler
Geri bildiriminiz için teşekkürler!
Yukarıda bulamadığınız her şey için destek ekibimiz her zaman yanınızda.