CHANGELOG

Sürüm Notları

Framework'ün sürüm tarihli değişiklik kaydı. Toplam 8 sürüm.

v0.9.7 güncelleme: 2026-10-14
v0.9.7

Eklendi

  • İçerik Fabrikası: direction.site_domain (sitenin kendi alan adı). Ayar dosyasındaki direction.site_domain değeri jobs yanıtında site_alan_adi olarak VPS'e gider; VPS CTA ve bağlantılarda bu alan adı dışında bir alan adı içeren yazıyı reddeder. Boş bırakılırsa davranış değişmez. Ayrıntı: docs/Packages/RbnFactory.md.

  • İçerik Fabrikası: eski yazıları yenileme (renew). Ayar dosyasına 'renew' => ['enabled', 'per_day', 'hours', 'order'] eklendi. jobs yanıtı, günlük sınır dolmadıysa yayındaki ve henüz yenilenmemiş (is_rewritten = 0) en eski yazı için kind: "renew" işi sunar (eski içerik gönderilmez). Sonuç yazıya hemen yazılmaz; iş kaydında bekler, yayın cron'u renew.hours saatinde sitenin içerik servisiyle (savePost) yazının içeriğini günceller, yazı aktif kalır ve is_rewritten = 1 olur. Bir yazıya ikinci renew işi açılması iş tablosundaki benzersiz indeksle (uq_factory_renew_post) veritabanı düzeyinde engellenir. İş tablosu ilk kullanımda kilit altında otomatik genişler (kind, renew_payload, renew_post_id; draft_id boş olabilir).

  • Eski içerik adresleri için otomatik 301. Yeni app_content_redirects tablosu (proje migration'ı) ve app.contentRedirect model/repository kaydı. ContentServiceTrait::savePost() bir yazının slug'ı ya da kategorisi değiştiğinde eski adresi bu tabloya yazar (panelden elle düzenleme ve fabrika yenilemesi aynı yoldan). resolveLegacyPostRedirect() önce bu tabloya bakar (kesin eşleşme, yazının güncel adresine tek adımda 301), yoksa eski benzer-slug yolu aynen sürer. Tablo olmayan projede davranış değişmez.

  • Global temizliğe hedefli tablo temizliği. system_global_cleanup cron satırının params alanına "targets": {"<proje>": {"<tablo>": {"days": N, "column": "<tarih_sütunu>"}}} yazılırsa CleanupJob yalnız o proje ve tablolardan column < şimdi-days satırlarını siler; başka proje taranmaz. Tablo/sütun/proje adı yalnız [a-z0-9_] olabilir; projede olmayan tablo ya da sütun atlanır ve sonuç cron günlüğüne proje·tablo=silinen olarak yazılır. params.target değeri targets ise yalnız bu hedefli dal çalışır. Mevcut genel temizlik değişmedi.

  • İçerik Fabrikası: yazı içi görseller images listesinde. result gövdesindeki images (src, alt, after_section, width, height) içeriğe <img> olarak gömülmez; yazı tablosunun images sütununa JSON yazılır (yeni yazıda en çok 2, yenilemede tam 1 öğe; sütun yoksa 422). Yenilemede kapak (image) değişmez. Yayın denetimi images dosyalarının varlığını da denetler; yenilemeden sonra eski gömülü <img> ve eski images dosyaları (kapak ve başka yazıda geçenler hariç) silinir.

  • BaseModel::hasColumn() ve ContentServiceTrait::hasPostColumn(). Projeye göre değişen isteğe bağlı sütunlar yazılmadan önce denetlenir. RbnStudio görsel üretimi image_prompt sütunu olmayan tabloda bu alanı yazmaz (kayıt hata vermez).

  • İçerik yazıları: yayın tarihi (published_at). Yazı tablosuna isteğe bağlı published_at DATETIME NULL sütunu. Fabrika yayın cron'u yazıyı açarken tarihi yalnız ilk yayında yazar (FactoryPostRepository::publishPost(), created_at ile aynı saat dilimi). Okuma kuralı FormatHelper::publishedAt(): published_at, yoksa created_at (pasif satırda created_at); sayfa tarihi, BlogPosting JSON-LD (datePublished, ayrıca dateModified = updated_at), kategori sırası ve ContentQueryTrait::getPosts() varsayılan sırası (COALESCE(published_at, created_at) DESC) bunu kullanır. Yeni komut rbn factory:published-at [--project=… --type=… --apply] sütunu ve indeksi ekler, yayındaki yazıları geriye dönük doldurur (idempotent). Sütunu olmayan sitelerde davranış değişmez. Ayrıntı: docs/Packages/RbnFactory.md. RSS pubDate (FeedResolver) aynı kuralı kullanır; genel sitemap içerik girdisinin lastmod değeri published_at doluyken updated_at ile yayın tarihinden büyük olandır (yayın tarihi yoksa eski kural: created_at, yoksa updated_at; girdinin açık lastmod verisi önceliklidir). Sayfa (/sayfa/…) girdileri değişmez.

Değişti

  • RbnApi / Shopier: ödeme linki üreten akış kaldırıldı, yerine ilan açma ve fiyat güncelleme geldi. Shopier REST API'de ödeme linki yok, satış mağaza ilanı üzerinden yapılıyor. ShopierService::createListing() ilanı açar (POST /products). updateListingPrice() fiyatı günceller (PUT /products/{id}); ilanın kimliği ve linki değişmez. İlanı ürüne kalıcı olarak bağlamak projenin işi; servis her istekte ilan açmaz. ShopierProvider::call() artık PUT ve DELETE isteklerini de JSON gövdeyle gönderiyor.

Kaldırıldı

  • ShopierService::generatePaymentUrl() ve verifyOrderOnline(). Her ödeme isteğinde stoku 1 olan yeni bir herkese açık ilan açıyorlardı ve mağazayı ilanla dolduruyorlardı.