Modül Anatomisi

1.8k görüntülenme Markdown

Bir modülü oluşturan dosyalar, birbirine uyması gereken üç ad ve taban sınıfın size hazır verdikleri.

Genel Bakış

Modül, zorunlu tek bir sınıf dosyası ve platformun adıyla aradığı isteğe bağlı dosyalardan oluşan bir dizindir. Hiçbir şey kaydedilmez: yükleyici her yolu tipten ve modül adından kurar. Doğru yerdeki dosya bulunur, adı yanlış yazılan ise uyarısız yok sayılır.

Tiplerin çoğu, hazırlığı zaten yapmış bir taban sınıf verir. İlk metodunuz çalışmadan önce modül kendi dizinini, açık URL'ini, yapılandırmasını ve dil metinlerini bilir. Sağlama tipleri hangi hizmet üzerinde çalıştığını da bilir. Bunlardan birini elle yeniden türetmek en sık yapılan acemi hatasıdır.

Yapı

Dosya Ağacı

tam bir modül, zorunlu ve isteğe bağlı
coremio/modules/{Type}/{Name}/
├── {Name}.php          # ZORUNLU: sınıf, dizinle aynı adı taşır
├── config.php          # dizi döndürür; ayarlar, künye, alan tanımları
├── logo.png            # ya da .svg/.webp/.jpg; yapılandırma ad vermezse addan bulunur
├── hooks.php           # Hook::add() kayıtları, HER istekte dahil edilir
├── AdminArea.php       # kendi admin sayfası, router.php'den kaydedilir
├── router.php          # include + ModuleAdminArea::register()
├── lang/
│   ├── en.php          # pratikte ZORUNLU: geri düşülen dil
│   └── tr.php          # çevrilen dil başına bir dosya
├── pages/              # ayar ve yönetim işaretlemesi, sayfa adıyla bulunur
├── views/              # aynı rol, alternatif dizin adı
├── controllers/        # controller dağıtıcısıyla ulaşılan adlandırılmış giriş noktaları
├── assets/
│   ├── style/          # css
│   ├── js/             # javascript
│   └── images/         # arayüz görselleri, logo değil
└── src/                # kendi yardımcı sınıflarınız, otomatik YÜKLENMEZ

Her Dosya Ne İçin

YolZorunluNe zaman okunurNe taşır
{Name}.phpEvetBir örnek kurulurkenSınıf. Yükleyiciye atlaması söylenmedikçe dahil edilir.
config.phpPratikte evetHer yüklemede, sınıfla ya da sınıfsızBir dizi: ayarlar, künye, alan tanımları, etkinlik işareti.
lang/en.phpEvetHer yüklemedeBir dizi. Etkin dilin dosyası yoksa kullanılan geri düşüş.
lang/{code}.phpİsteğe bağlıO dil etkinkenAynı anahtarların çevrilmiş hali.
logo.png ve benzerleriİsteğe bağlıPanel modülü gösterirkenSimge. Yapılandırma dosya adı vermediğinde uzantıdan bulunur.
hooks.phpİsteğe bağlıHer istekte, diskteki her modül içinKanca kayıtları. Modül etkin olsun olmasın çalışır.
AdminArea.php artı router.phpİsteğe bağlıHer istekte, yönlendirmeden önceKendi admin sayfanız: rota, menü öğesi, yetkiler.
pages/ ya da views/İsteğe bağlıBir sayfa gösterilirkenSayfa adıyla çağrılan işaretleme; iki dizin adı da denenir.
controllers/İsteğe bağlıAdlandırılmış bir controller çağrılırkenGiriş noktası başına bir dosya; aynı addaki metottan önce denenir.
assets/İsteğe bağlıTarayıcı istediğindeStil, betik ve görsel dosyaları; URL özelliğiyle adreslenir.
src/İsteğe bağlıKendiniz dahil ettiğinizdeAPI istemciniz ve yardımcılarınız. Otomatik yükleyici buraya ulaşmaz.

Referans

Birbirine Uyması Gereken Üç Ad

Dizin adı Modül adı ve yükleyiciye verilen tek şey. Harfe duyarlı bir dosya sisteminde harf durumu anlamlıdır: cPanel, CPanel değildir.
Sınıf dosyası adı Dizin adı artı .php. Yükleyici bu yolu kurar, başka yere bakmaz.
Sınıf adı Sırayla üç aday denenir. _Module son ekli ad, global ad alanındaki çıplak ad, sonra tip ad alanı altındaki ad. Yeni modülleri üçüncü biçimde yazın.
Ad alanı WISECP\Modules\{Type}, tip dizinde nasıl yazılıyorsa öyle. İçeride çıplak bir çekirdek sınıf adı modül ad alanına çözülür ve çalışma anında düşer. Çekirdek sınıfları içe aktarın ya da başlarına ters bölü koyun.

Tipe Göre Taban Sınıf

On altı tipin sekizinde taban sınıf vardır. Kalanı hiçbir şey devralmaz; sözleşmeleri, çekirdeğin aradığı metotlardan ibarettir.

Taban sınıfTipOrtak traitYapıcısının çoktan yaptığı
ServerModuleServersEvetYollar, yapılandırma, dil, oturumdaki admin, varsayılan araç kümesi ve verildiyse sunucu.
PaymentGatewayModulePaymentHayırYollar, yapılandırma, dil, ödeme butonu etiketi, boş bir müşteri bilgisi nesnesi.
RegistrarModuleRegistrarsEvetYollar, yapılandırma, dil ve şifreleme alt anahtarının kullanıcı anahtarından sistem anahtarına geçirilmesi.
ProductModuleProductEvetYollar, yapılandırma ve dil, başka bir şey değil.
SslProductModuleProductDevralınırSoyut. Ürün tabanı, artı her sertifika modülünün yanıtladığı doğrulama, yeniden düzenleme ve SAN sözleşmesi.
AddonModuleAddonsHayırYollar, yapılandırma, dil, admin alan bağlantısı, oturumdaki admin ile üye kayıtları.
FraudModuleFraudHayırYollar, yapılandırma, dil, mevcut controller bağlantısı, oturumdaki kimlikler.
StorageModuleStorageHayırSoyut. Depolama yapılandırmasını yapıcı dizisi olarak alır; dizin ya da URL özelliği yoktur.
SocialAuthProviderSocialAuthEvetSoyut. Yollar, yapılandırma ve dil; her uç nokta ve jeton doğrulaması soyut kalır.

Devralınan Özellikler

Ortak trait'ten gelir; sunucu, servis sağlayıcı, ürün ve sosyal giriş modüllerinde aynıdır.

ÖzellikTipKim doldururNe taşır
$_namestringYapıcıModül adı; siz vermezseniz sınıfın kısa adı.
$_typestringYapıcıTip dizini, taban sınıf onu nasıl bildirdiyse.
$dirstringYapıcıModül dizininin mutlak yolu, sonunda ayraçla.
$urlstringYapıcıModül dizininin açık URL'i, sonunda eğik çizgiyle. Varlık bağlantılarını bundan kurun.
$configarrayYapıcıYüklenmiş haliyle config.php dizisinin tamamı.
$langarrayYapıcıModülün etkin dildeki metinleri.
$servicearrayHizmet bağlanıncaHizmet kaydının tamamı; bir hizmet bağlanana kadar boş.
$productarrayHizmet ya da ürün bağlanıncaHizmetin sipariş edildiği ürün.
$orderarraySipariş bağlanıncaSipariş kaydı; siparişten sağlama sırasında.
$userarrayHizmet bağlanıncaSahibin kimliği, iletişim bilgileri ve fatura adresi.
$adminarrayHizmet bağlanıncaİşlemi yapan admin; panel dışında boş.
$optionsarrayHizmet bağlanıncaHizmetin seçenekleri; modülün hizmet başına durumunu sakladığı yer.
$addonsarrayHizmet bağlanıncaHizmetin ek kayıtları, ek kimliğine göre anahtarlanmış.
$addon_paramsarrayHizmet bağlanıncaToplama katılmış ek değerleri; iptal ve bekleyen ekler hariç.
$addon_params_by_idarrayHizmet bağlanıncaAynı değerlerin ek başına hali, iptal edilenler dahil.
$requirement_paramsarrayHizmet bağlanıncaMüşterinin ürün gereksinimi yanıtları, sizin parametre adınıza göre anahtarlanmış.
$callable_methodsarraySiz bildirirsinizURL'den çıplak adla çağrılabilen metotların izin listesi; dışındakiler çağrılamaz.
$errorstringYeni kodda hiçbir şeyÖnceki ana sürümden kalma. Hataları fırlatarak bildirin.

Devralınan Yardımcılar

imzalar, ortak trait'ten
// Bağlam bağlama. Her biri bir id YA DA yüklenmiş kaydı alır; int verirseniz sizin için çekilir.
public function set_service(array|int $service = []): void;
public function set_product(array|int $product = []): void;
public function set_order(array|int $order = []): void;

// $this->options değerini bağlı hizmete geri yazar. Hiçbir şey bağlı değilse false.
public function save_options(): bool;

// config.php'yi yeniden yazar. $auto_status = true, ayar dizisi varken durumu açık konuma çevirir.
protected function save_config($data = [], $auto_status = true);

// Sağlayıcı çağrısı başına bir günlük satırı, panelin işlem geçmişinde gösterilir.
protected function save_log($action = '', $request = '', $response = '', $processed = ''): int|bool;

// Modülün şifreleme alt anahtarıyla şifreler; $key tek çağrılık olarak onu ezer.
protected function encode_str(string $str = '', string $key = ''): string;
protected function decode_str(string $str = '', string $key = ''): string;

// Çözülmüş logo URL'i ya da boş dize.
public function logo(): string;

// Bağlı hizmette etkin olan metrik sınırları, metrik tipine göre anahtarlanmış.
protected function enabled_metrics(): array;
protected function enabled_metric_values(): array;
protected function reapply_enabled_metrics(): void;

// Seçeneklerini metotlarınızdan birinden yükleyen bir açılır liste için veri öznitelikleri.
protected function method_url_data(string $method): array;

// "reset-password" adını handle_reset_password() metoduna yönlendirir. Yoksa null döner.
protected function use_method($param = '');

// Tek bir seçeneğin eklenti değerleri; parametre hariç tutmadıkça adetle çarpılır.
public function resolveAddonConfigurable(array $moduleParams, int $quantity = 0): array;
save_config() Dizinin tamamını yazar; önce mevcut yapılandırmayla birleştirin. Bir ayar yazımı modülü etkinleştirmemeliyse ikinci argümanı false geçin.
encode_str() Alt anahtar argüman değil özelliktir: varsayılanı user, servis sağlayıcı tabanı ise onu system yapar. Bir anahtarla şifrelenen değer diğeriyle çözülmez.
use_method() Tireli bir eylem adını, tireleri alt çizgiye çevirerek handle_ önekli bir metoda eşler. Başka bir ad, panel eylem butonlarından erişilemez.
save_log() Diziler sizin için kodlanır. İstek URL'ini istek dizisine api_url anahtarıyla koyun; kendi kolonuna çıkarılır.

Eklenti İstisnası

Bir eklenti modülü ortak trait'i kullanmaz. Yukarıdaki özelliklerin hiçbiri onda yoktur; yalnız kendi tabanının bildirdiği dördü vardır. Sunduğu arayüz daha küçük ve farklıdır.

eklenti tabanının tamamı
// Özellikler: $config, $lang, $dir, $url, $area_link, $_name, $user, $admin, $error.
public function __construct();

// views/{file}.php dosyasını, $variables içine açılmış halde render eder. İşaretlemeyi döndürür.
protected function view($file = '', $variables = []): string;

// Bu eklentinin admin rol ekranına eklediği yetki anahtarları.
public function privileges();

// Eklenti ayarları ekranı çağırır: $pFields gönderilen ayarlar,
// $accessPs ise gönderilen yetki seçimidir.
public function save_settings($pFields, $accessPs): bool;

// Eklenti listesinden etkinleştirme ya da devre dışı bırakma.
public function change_addon_status($arg = '');

// config.php'yi yeniden yazar. Tek argümana dikkat: burada otomatik durum bayrağı yok.
public function save_config($data = []): bool;

// Aynı şifreleme yardımcıları, ama eklenti tabanı alt anahtarı varsayılan olarak 'system' yapar.
protected function encode_str(string $str = '', string $key = ''): string;
protected function decode_str(string $str = '', string $key = ''): string;

public function use_default_settings($formElements = null);
public function isEnabled();

Örnek

Devraldığı hiçbir şeyi yeniden bildirmeyen bir modül iskeleti ve onu süren çağıran taraf. Zorunlu tek dosya sınıf dosyasıdır.

coremio/modules/Registrars/AcmeDomains/AcmeDomains.php
namespace WISECP\Modules\Registrars;

use Exception;
use Language;
use RegistrarModule;
use WISECP\Modules\Registrars\AcmeDomains\ApiClient;

class AcmeDomains extends RegistrarModule
{
    private ?ApiClient $api = null;

    // Yapıcı yok. Taban yapıcı $_name, $_type, $dir, $url, $config ve $lang değerlerini zaten kurdu.
    // Onun yerine istemciyi tembel kurun: hizmet yapıcıdan SONRA bağlanır, yani
    // $this->service gerektiren hiçbir şey burada koşamaz.
    private function api(): ApiClient
    {
        if ($this->api) return $this->api;

        // src/ otomatik yüklenmez, bu yüzden dosya açıkça dahil edilir.
        include_once $this->dir . 'src' . DS . 'ApiClient.php';

        $settings = $this->config['settings'] ?? [];

        $this->api = new ApiClient(
            (string) ($settings['username'] ?? ''),
            $this->decode_str((string) ($settings['apiKey'] ?? '')),
        );

        return $this->api;
    }

    // create() DEĞİL. create() taban sınıfa aittir ve EPP kodunun varlığına göre
    // register() ya da transfer() metoduna yönlendirir. create() metodunu geçersiz kılmak
    // transfer dalını ve onun iki kancasını birden düşürür.
    public function register(): array|bool
    {
        // Bağlı kayıt, sipariş edilen alan adını options içinde taşır; service['name']
        // geri düşüştür. Hizmetin kendisinde 'domain' diye bir kolon yoktur.
        $domain = (string) ($this->options['domain'] ?? $this->service['name'] ?? '');
        if ($domain === '') throw new Exception(Language::gc("acme/error-no-domain"));

        // 'year' tescil süresidir. service['period'] ise faturalama döngüsü
        // dizesidir ('y', 'm', 'none'), asla yıl sayısı değil.
        $year = (int) ($this->options['year'] ?? $this->service['period_time'] ?? 1) ?: 1;

        $response = $this->api()->register($domain, $year);

        // Her sağlayıcı çağrısı kaydedilir; api_url kendi kolonuna çıkarılır.
        $this->save_log('register', ['api_url' => $this->api()->last_url, 'domain' => $domain], $response);

        if (!($response['ok'] ?? false))
            throw new Exception($response['message'] ?? Language::gc("acme/error-refused"));

        return true;
    }
}
onu süren taraf
$module = Modules::getInstance("Registrars", "AcmeDomains");
if (!$module) throw new Exception(Language::gc("modules/error-not-found"));

// Bağlama ayrı bir adımdır ve $service, $product, $user ile $options değerlerini dolduran şeydir.
$module->set_service($serviceId);

try {
    // Çağıran taraf her zaman create() ister. Servis sağlayıcıda bu, taban metottur:
    // register() ya da transfer() metoduna yönlendirir ve çevresinde alan adı kancalarını koşturur.
    $result = $module->create();
}
catch (\Throwable $e) {
    // Modül başarısızlığı fırlatarak bildirir; çağıran taraf mesajı yanıta çevirir.
    return $operation->output(['status' => "error", 'message' => $e->getMessage()]);
}

// Modülün değiştirdiği durum, kendi yardımcısı üzerinden hizmete geri yazılır.
$module->save_options();

Tuzaklar

Diskteki her modülün kanca dosyası her istekte çalışır

Kapalı ya da yarım kalmış bir modül de kancalarını kaydeder. Gövdeyi modülün kendi etkinlik işaretiyle kapılayın, pahalı işi dosyadan uzak tutun.

Kendi yardımcı sınıflarınız otomatik yüklenmez

Otomatik yükleyici tip ad alanını tip dizinine eşler ve orada durur; modülün kaynak klasöründeki bir içe aktarma hiçbir dosyayı yüklemez. İlk kullanımdan önce dahil edin. Bir kanca içindeki ölümcül hata, o kanca gövdesinin geri kalanını sessizce öldürür.

Niteliksiz bir çekirdek sınıf adı sizin ad alanınıza çözülür

Ad, modül ad alanı altında aranır ve bulunamaz; üstelik lint anında değil çalışma anında. Dosya çalışıyor görünür, çünkü içe aktardığınız sınıflar sorunsuzdur.

API istemcisini yapıcıda kurmayın

Yapılandırma ve dil orada hazırdır ama hizmet, ürün, sahip ve seçenekler sonradan bağlanır. Yapıcı anında hizmet verisinden kurulan bir istemci boş değer okur ve sağlayıcıya karşı, gerçek sebebin yanından geçmeyen bir mesajla düşer. İstemciyi ilk kullanımda tembel kurun.

Bazı taban metotları boş yuva değil, yönlendiricidir

Çekirdeğin çağırdığı bir ad, sizin yazacağınız ad olmak zorunda değildir. Servis sağlayıcıda create() tabanda tanımlıdır: tescil ile transfer arasında karar verir, kapı ve eylem kancalarını çalıştırır, gönderilmiş bir transferi bekleyen duruma çevirir. Sizin yazdığınız register() ve transfer()'dır. Geçersiz kılmadan önce tabana bakın.

İki dizin adı aynı anlama gelir

configuration ve settings adları da birbirinin yerine denenir. Her birinden birini seçin ve ona bağlı kalın.

Faydalı oldu mu?

Geri bildiriminiz için teşekkürler!

Hâlâ Yardıma mı İhtiyacınız Var?

Yukarıda bulamadığınız her şey için destek ekibimiz her zaman yanınızda.