# Modülü Dağıtıma Hazırlama

https://dev.wisecp.com/tr/modulu-dagitima-hazirlama

Bir modül dizinini başkasının kurabileceği arşive dönüştürün: içinde ne olmalı, asla ne olmamalı.

## Genel Bakış

Paket, yolu korunarak ziplenmiş tek bir dizindir. Onu iki taraf okur ve aynı şekilde okumazlar.

| Okuyan | Neyi kabul eder | Sonuç |
| --- | --- | --- |
| Panelden elle yükleme | Tam ağaç: kökte bir `coremio` dizini | Sistemin köküne, dosya dosya birleştirilir |
| Güncelleme sihirbazı | Modül klasörü, tam ağaç ya da adsız klasör | Geri alma kopyasından sonra modülün dizinine |
| Store indirmesi | Kökte modül klasörü | Modül dizinine, ardından bir manifest |

Üçünü birden karşılayan tek biçim: **tam ağacı gönderin**, kökü `coremio/modules/{Type}/{Name}/` olsun.

## Ön Koşullar

- **Temiz bir kopyada çalışan bir modül**: Önce boş bir sisteme kurun; elle eklediğiniz bağımlılık başkasında eksik olur.
- **Hiçbir yerde mutlak yol yok**: Yolları sabitlerden kurun.
- **Nötr bir config dosyası**: Her ayarı boşaltın, sonra üretilen arşivi denetleyin.
- **Yeniden kullanmayacağınız bir sürüm numarası**: Sistemlerin karşılaştırdığı kimlik olur; derlemeden önce karar verin.
- **Bir İngilizce dil dosyası**: Çevirmediğiniz her dilde yükleyici ona düşer.

## Yapı

Modülünüze ait her şey, sınıfıyla aynı adı taşıyan tek bir dizinde yaşar.

```bash
AuroraBackup-1.2.0.zip
 └─ coremio/
     └─ modules/
         └─ Addons/
             └─ AuroraBackup/
                 ├─ AuroraBackup.php     # sınıf; yükleyici tam olarak bu adı arar
                 ├─ config.php           # ayarlar ve künye; varsa güncelleme atlar
                 ├─ manifest.json        # kopyayı güncelleme kontrolüne kaydeder
                 ├─ hooks.php            # isteğe bağlı, kanca sistemi yükler
                 ├─ router.php           # isteğe bağlı, bir admin sayfası kaydeder
                 ├─ AdminArea.php        # isteğe bağlı, admin sayfasının kendisi
                 ├─ logo.png             # isteğe bağlı, adıyla bulunur
                 ├─ lang/
                 │   ├─ en.php           # geri düşülen dosya, her zaman gönderin
                 │   └─ tr.php
                 ├─ views/
                 │   └─ index.php
                 └─ src/
                     └─ ApiClient.php    # kendi yardımcı sınıflarınız
```

Dizini yeniden adlandırdığınızda sınıf çözümü, güncelleme tanıması ve logo birden durur.

## Adım Adım

### Dizini kurun

Dört dosya sabit yerlerden okunur.

1. `{Name}.php` sınıfı bildirir; fabrika sırayla `{Name}_Module`, `{Name}` ve ad alanlı biçimi dener.
2. `config.php` bir dizi döner: `status` eklentiyi açılabilir yapar, `meta` adı, yazarı, ikonu taşır.
3. `lang/{code}.php` düz bir dizi döner; önce aktif dil, yedek İngilizce.
4. `manifest.json` kurulu kopyayı güncellenebilir yapar.

### Arşiv biçimi

Tam ağacı sistemin kökünden, yalnız kendi dizininizle zipleyin.

```bash
# Temiz bir sistemin kökünden; böylece saklanan yollar köke göreli olur.
zip -r AuroraBackup-1.2.0.zip coremio/modules/Addons/AuroraBackup \
    -x '*/.git/*' '*/.DS_Store' '*/node_modules/*' '*.log' '*.map'

# Arşivi geri okuyun ve bakın. Göndermeyi düşündüğünüz şeyi değil gerçekten
# gönderdiğiniz şeyi görmenin tek yolu budur.
unzip -l AuroraBackup-1.2.0.zip
```

Zip içindeki zip bir kez açılır ve hiçbir düzene uymaz.

### Gitmemesi gerekeni ayıklayın

Artıklar paketi büyütür; kimlik bilgileri ve başıboş dosyalar hedefte zarar verir.

Çalışma dizinini değil, üretilen arşivi okuyun.

### Hedef sistemde ne olur

Operatör arşivi panelden yükler; sonrası sabittir.

1. Yükleme doğrulanır: `.zip` ya da `.tar.gz`, boyut tavanının altında.
2. Dosya `temp` altına konur ve bir çalışma klasörüne açılır.
3. Arşivdeki `coremio` kökü, ağacın tamamını sistemin köküne taşıtır.
4. Çalışma klasörü ve yüklenen arşiv her hâlükârda silinir.
5. Eklenti aynı işlemde açılabilir; bu sizin `enable()` metodunuzu çağırır.

```php
public function enable(): bool
{
    // Modülün var olabilmesi için gereken her şey: tabloları, bildirim şablonları,
    // tohum satırları. İdempotent, çünkü bir operatör modülü canı istediği kadar
    // kapatıp yeniden açabilir.
    $this->check_database();

    // Kolon onarımı tablo oluşturmadan sonra koşar, asla onun içinde değil: sonradan
    // eklenen bir kolona yazan tohumlama, tablosu o kolondan eski olan bir sistemde ölür.
    $this->check_columns();

    // false döndürmek açma işlemini iptal eder ve modülü kapalı bırakır; bu yüzden onu
    // gerçek bir engel için kullanın, asla bir uyarı için değil.
    return true;
}
```

Bu yol manifest yazmaz ve anahtarı olmayan tipler için `enable()` çalıştırmaz: sunucu ya da servis sağlayıcı modülü ihtiyacını başka bir yolda kurar.

### Yayınlamadan önce doğrulayın

Üretilen arşivi boş bir sisteme açın ve geri okuyun.

```php
<?php
require dirname(__DIR__) . '/bootstrap.php';

$type = 'Addons';
$key  = 'AuroraBackup';
$dir  = MODULE_DIR . $type . DS . $key;

$fail = [];

// 1. Platformun sabit yerlerden okuduğu dört dosya.
foreach ([$key . '.php', 'config.php', 'manifest.json', 'lang' . DS . 'en.php'] as $file)
    if (!is_file($dir . DS . $file)) $fail[] = 'missing: ' . $file;

// 2. Yükleyicinin kendi yanıtı, bizim tahminimiz değil.
Modules::Load($type, $key, true);
$config = Modules::Config($type, $key);
if (!is_array($config)) $fail[] = 'config.php did not return an array';

// 3. Derlemeden sağ çıkan kimlik bilgileri. GÖNDERİLEN ayarları okuyun, notlarınızı değil.
foreach ((array) ($config['settings'] ?? []) as $name => $value)
    if (is_string($value) && $value !== '') $fail[] = 'setting not blank: ' . $name;

// 4. Güncelleme kaydı.
if (!ModuleUpdater::manifest($dir)) $fail[] = 'manifest.json unreadable: no updates would ever be offered';

echo $fail ? implode("\n", $fail) . "\n" : "package looks shippable\n";
```

## Referans

### Platform neyi okur

| Dosya | Kim okur | Olmazsa ne olur |
| --- | --- | --- |
| `{Name}.php` | yükleyici; sihirbazın doğruluk kanıtı | Hiçbir düzene uymaz, hiçbir şey örneklenemez |
| `config.php` | yükleyici, her registry kurulumunda | Ayar ve durum olmaz: yüklenir ama işlevsiz |
| `lang/en.php` | yükleyici, yedek olarak | Çevrilmemiş dillerde etiketler boşa çözülür |
| `lang/{code}.php` | yükleyici, aktif dilde | O dil İngilizceye düşer |
| `manifest.json` | günlük güncelleme kontrolü | Kopya elle kurulmuş sayılır, hiç güncellenmez |
| `logo.*` | logo çözücüsü, glob ile | Config adlandırmadıysa logo görünmez |
| `hooks.php` | kanca sistemi, açılışta | Hiçbir şey kaydolmaz |

### Yükleme sınırları

- **Uzantı**: Yalnız `.zip` ve `.tar.gz` kabul edilir; çıkarma işi ZipArchive ile yapılır.
- **Boyut**: 50 MB tavanı; sunucunun kendi sınırları bunun öncesinde.
- **Arşiv kökünde bir coremio dizini**: Modül anahtarı tip klasörü altındaki ilk dizinden gelir; kökü olmayan arşiv reddedilir.
- **Var olan dosyaların üstüne yazılır**: Taşıma dosya dosya: aynı yoldakiler değişir, diğerlerine dokunulmaz.
- **Temp her zaman temizlenir**: Başarıda da hatada da silinir; başarısız kurulum inceleyecek bir şey bırakmaz.

### Arşivde asla bulunmaması gerekenler

| Göndermeyin | Neden |
| --- | --- |
| `coremio/modules/{Type}/{Name}/` dışındaki her şey | Bir çekirdek dosyasının yerine geçer, sessizce |
| `config.php` içindeki API anahtarları ve test hesapları | Ayarlar dizisi diskinizdeki hâliyle gider |
| Değiştirmediğiniz bir lisans açık anahtarı | Taklit lisans yanıtını değersiz kılan tek şey odur |
| Sürüm kontrolü ve editör dizinleri | Geçmiş, dal adları ve loglarda kalan kimlik bilgileri |
| Bağımlılık ve derleme dizinleri, kaynak haritaları | Kaynak haritası derlemenin gizlediğini geri açar |
| Geliştirme sırasında yazılmış deneme betikleri | Başkasının sunucusunda erişilebilir dosyaya dönüşür |
| Loglar, dökümler, yedekler ve depolama çıktısı | Başkasının verisi; bayat ve kişisel olabilir |
| Arşivin içinde ikinci bir arşiv | Açma bir kez olur, sonuç hiçbir düzene uymaz |

### Giriş noktaları

```php
// İki yükleme yolunun da paylaştığı arşiv işleyicisi. $name boşsa "anahtarı ağaçtan
// çıkar" demektir; elle yükleme yolunun tam ağaca ihtiyaç duymasının sebebi budur.
public function extract_archive($file = '', $name = '', $group = 'Addons'): string;

// Kayıt defterine alma: önce config.php, sonra lang/{active}.php okunur, geri düşüş
// lang/en.php'dir; sınıf zaten bildirilmemişse {Name}.php dahil edilir.
public static function add($file, $type, $nominc = false, $status = '');
public static function Load($type = '', $name = '', $nominc = false, $status = '');

// getInstance bu üç sınıf adından var olan İLKİNİ alır, şu sırayla:
//   {Name}_Module  ->  {Name}  ->  WISECP\Modules\{Ucfirst Type}\{Name}
// Eksik yapıcı argümanları null ile doldurulur; yani sınıfınızın null olarak baş
// edemediği zorunlu bir parametre, yardımcı bir hata değil örnekleme anında bir çöküştür.
public static function getInstance(string $type, string $name, array $params = []): ?object;

// Bir eklentiyi açma. Önce activate(), sonra enable() çağrılır ve bayrak yalnız
// sonuncusu true döndüyse yazılır.
public function change_addon_status($arg = '');

// Store kurulum yolu yazar; diğer her yolda paketin içinde siz yazarsınız.
public static function write_manifest(string $dir, array $manifest): bool;
```

- **AdminTools::extract_archive()**: Anahtar biliniyorsa tek klasör, bilinmiyorsa ağacın tamamı köke taşınır.
- **Modules::add()**: Dört sabit dosya adının okunduğu yer; sınıfı ikinci kez dahil etmez.
- **Modules::getInstance()**: Örnek almanın kanonik yolu; asla `new` kullanmayın.
- **AddonModule::change_addon_status()**: Enable ve disable metotlarınızın tek çağıranı.
- **ModuleUpdater::write_manifest()**: Yalnız store yolu çağırır; manifest sizin arşivinizde gitmelidir.

## Örnek

Paketlenmiş ücretli bir eklenti: kurulup kurulmayacağına üç dosya karar verir.

```bash
$ unzip -l AuroraBackup-1.2.0.zip
  coremio/modules/Addons/AuroraBackup/AuroraBackup.php
  coremio/modules/Addons/AuroraBackup/config.php
  coremio/modules/Addons/AuroraBackup/manifest.json
  coremio/modules/Addons/AuroraBackup/hooks.php
  coremio/modules/Addons/AuroraBackup/logo.png
  coremio/modules/Addons/AuroraBackup/lang/en.php
  coremio/modules/Addons/AuroraBackup/lang/tr.php
  coremio/modules/Addons/AuroraBackup/views/index.php
  coremio/modules/Addons/AuroraBackup/views/unlicensed.php
  coremio/modules/Addons/AuroraBackup/src/ApiClient.php

# coremio/modules/Addons/AuroraBackup üstünde hiçbir şey yok. .git yok, node_modules yok,
# geçici betik yok, ikinci arşiv yok, depolama çıktısı yok.
```

```php
<?php
return [
    'created_at'         => 1785312000,
    'meta'               => [
        'name'         => 'Aurora Backup',
        'version'      => '1.2.0',
        'author'       => 'Aurora Systems',
        'opening-type' => 'normal',
        'icon_type'    => 'font',
        'icon'         => 'bi bi-cloud-arrow-up',
        'slug'         => 'aurora-backup',
    ],
    'show_on_adminArea'  => true,
    'show_on_clientArea' => false,

    // Kapalı gönderilir: operatör açar ve enable() metodunu çağıran şey odur.
    'status'             => false,
    'access_ps'          => [],

    // Her değer boş. Bu dizi diskinizden olduğu gibi geri yazılır.
    'settings'           => [
        'api_endpoint' => '',
        'api_key'      => '',
        'bucket'       => '',
    ],
];
```

```json
{
    "type": "marketplace",
    "id": 42,
    "version": "1.2.0",
    "last_updated": "2026-08-03"
}
```

Sürüm iki kez geçer: config bloğunu operatör okur, manifest'i her güncelleme karşılaştırır.

## Tuzaklar

> **Ağacı değil klasörü ziplemek**
> 
> Kökü modül klasörü olan arşiv sihirbazdan geçer; elle yükleme onu reddeder.

> **Test config'ini göndermek**
> 
> Kimse onu sizin yerinize boşaltmaz. Boşaltmayı bir derleme adımı yapın ve arşivi denetleyin.

> **Eksik manifest kopyayı dondurur**
> 
> Hiçbir şey düşmez ve modül çalışır, ama bir daha hiç güncelleme sunulmaz.

> **Yalnız kendi dilinizi göndermek**
> 
> Yedek İngilizcedir, o yüzden yalnız Türkçe dosyası olan modül başka panellerde boş etiket gösterir.

> **Önce kendi paketinizi kurun**
> 
> Müşterinin yapacağı gibi yükleyin, açın, sonra bir önceki sürümden güncelleyin.

## İlgili Makaleler

- [Ürün Yayınlama](https://dev.wisecp.com/tr/pazar-yerinde-urun-yayinlama)
- [Modül Güncellemesi Yayınlama](https://dev.wisecp.com/tr/modul-guncellemesi-yayinlama)
- [Modül Lisanslama](https://dev.wisecp.com/tr/modul-lisanslama)
- [Modül Anatomisi](https://dev.wisecp.com/tr/modul-anatomisi)
- [Modül Dil Dosyaları](https://dev.wisecp.com/tr/modul-dil-dosyalari)
- [Modül Varlıkları ve Logo](https://dev.wisecp.com/tr/modul-varliklari-ve-logo)
- [Modül Yaşam Döngüsü](https://dev.wisecp.com/tr/modul-yasam-dongusu)
