RBN Core - Framework v0.9.7 76 belge

RbnAdmin/Providers + Services + Traits — analiz ve sunum katmanı

Doğrulanan kod tabanı: d49b4413 (dal feat/fw-license-master) · Tarih: 2026-10-05 · Yayın: 0.9.7 = bu commit + sonrası; belge yalnız doğrulama anındaki kodu anlatır
Kaynak klasörler: Bundles/RbnSuite/RbnAdmin/{Providers,Services,Traits}/
— 7 *.php (Providers 4 · Services 2 · Traits 1)
Envanter: 7 dosyanın 7'si anlatıldı.
Üst belge: README.md

1. Ne işe yarar, kimler kullanır

Bu üç klasör, RbnAdmin'ın "veriyi topla ve sun" katmanıdır. Hiçbiri HTTP
bilmez, hiçbiri rota tanımlamaz. Çağıranlar:

Kontrolör → servis → kanal → depolama zinciri:
WebtrafficController → AnalyticsService::traffic() → TrafficStatsChannel
→ TrafficAnalysisTrait::get() → $this->storage->traffic()->get('date_…').

2. Dosya envanteri (7 dosya)

Dosya Tür Görev Önemli yöntemler
Providers/AnalyticsProvider.php BaseProvider Trafik + kullanıcı istatistiğinin örgütlenmemiş toplayıcısı; $targetModel = 'Users' (:18) getDashboardStats(): array (:25), getUserStats(): array (:43)
Providers/SocialMediaProvider.php BaseProvider JSON dosyasından platform tanımlarını yükler, akıcı ("self" döndüren) arayüz sunar __construct(), getPlatform(string $key): self, all(bool $sortByOrder=true): array, total(): int, exists(): bool, title(), icon(), faIcon(), riIcon(), color(), order(), shareUrl(), shareClass()
Providers/Fluent/TrafficStatsChannel.php BaseChannel Trafik kanalı; her okuma önbellekten __construct() → parent::__construct('analytics_traffic') (:20), stats(), summary(), hits(): int, trend()
Providers/Fluent/UserStatsChannel.php BaseChannel Kullanıcı kanalı; aynı önbellek deseni __construct() → parent::__construct('analytics_users') (:18), get(), count(): int, stats(), total(): int, distribution(), roles(), all()
Services/AnalyticsService.php BaseService Kanallara ve GA4'e tek giriş kapısı users(): UserStatsChannel, traffic(): TrafficStatsChannel, record(array $data=[]), isGoogleAnalyticsActive(): bool, getGoogleAnalyticsReports(?string $s=null, ?string $e=null, string $type='standard')
Services/RbnAdminService.php BaseService Tema rengi kaydı (yetki kontrollü) + paylaşım düğmeleri saveColors(string $p, ?string $s=null, ?string $projectKey=null): bool (:24), allSocialPlatforms(bool $sortByOrder=true): array, socialPlatform(string $key): object, totalSocialPlatforms(): int, getShareButtons(string $url, string $title): array (:81)
Traits/TrafficAnalysisTrait.php trait Trafik sorgu dilini ve özet hesabını tanımlar withProject(?string $pk), query(), forDate(string), forToday(), forRange(string,string), forTrend(int), limitQuery(int), get(): array, count(): int, computeSummary(): array, devices(): array, top(string $key, int $limit=5): array, getActiveCount(int $minutes=5): int, all(), hits(): int

Kayıt yolları. AnalyticsService, RbnAdminService ve iki provider
Models/ModuleData.php:33 registerMap() ile paket adı altında kayıt edilir
(analytics, socialmedia, rbnAdmin, analytics(provider), social(provider)).
Ayrıca RbnAdminService ve SocialMediaProvider global kayıt defterinde de vardır
(Core/System/Registries/RegistryMap/SystemLogicMapTrait.php:78 ·
SystemPhysicalMapTrait.php:79) — yani aynı sınıfa iki ayrı anahtardan
(socialmedia paketten ve globalden) erişilebilir; ikisi de aynı sınıfı gösterir.

3. Akışlar

3.1 Trafik özeti (dashboard'ın kullandığı yol)

service('analytics')->traffic()->summary()      AnalyticsService.php:31
  → new TrafficStatsChannel()                   TrafficStatsChannel.php:18
  → getFromCache('summary', computeSummary)     TrafficStatsChannel.php:44
      → TrafficAnalysisTrait::computeSummary()  TrafficAnalysisTrait.php:137
          ├─ storage->traffic()->getMonthlyData(date('Y-m'))          :150
          ├─ listDates() → her AY için getMonthlyData() → toplamlar  :167-187
          ├─ bot temizliği: 'Bot' öneki olan yerler çıkarılır         :192-202
          ├─ active_now = getActiveCount(5)                            :217
          └─ seven_day_trend / top_pages / top_sources                 :222-234

3.2 Önbellek anahtarı nasıl üretiliyor

BaseChannel::getFromCache() (Core/Base/Patterns/BaseChannel.php:252-…) anahtarı
şunlardan kurar: kanal adı (analytics_traffic / analytics_users) + filtreler +
sıralamalar + arama terimi + hidrasyon modu → md5(json_encode($state))
(:261-271), artı proje anahtarı (:277-294: önce ?project= sorgusu,
düşerse project_key()). Yani trafik istatistikleri proje başına ayrı
önbelleklenir.

json_encode başarısız olursa (INF/NAN/geçersiz UTF-8) yedek karma
print_r ile üretilir; ölçülen 3 bozuk filtre durumu tek anahtara düşmesin diye
eklenmiştir (BaseChannel.php:255).

3.3 Tema kaydı ve yetki

RbnAdminController::saveTheme()                   RbnAdminController.php:166
  → request->form([… regex:/^#[0-9A-Fa-f]{6}$/])  :169-173
  → RbnAdminService::saveColors()                 RbnAdminService.php:24
      ├─ handler('access')->can('admin')  → değilse throw            :27-30
      ├─ projectKey ?: project_key() ?: 'default'                    :32
      └─ service('settings')->updateSettings($settings, $projectKey) :43
  → Route->handleResult($result)                                     :185

$settings dizisine yalnız dolu gelen renkler eklenir (:38-40); ikincil renk
boşsa hiç yazılmaz, yani bir önceki değer korunur.

3.4 Paylaşım düğmeleri

getShareButtons() (:81-114) tüm platformları gezer, yalnız shareUrl() ve
shareClass() dolu olanları alır; {url}/{title} yer tutucularını
urlencode() edilmiş değerlerle değiştirir (:95-99).

4. Yapılandırma / varsayılanlar

Değer Kaynak satırı Varsayılan / etki
Platform veri dosyası SocialMediaProvider.php:27 Resources/Data/social_media_platforms.json; yoksa boş dizi
all() sıralaması SocialMediaProvider.php:53 order alanına göre uasort; alan yoksa 999
getPlatform() bilinmeyen anahtar SocialMediaProvider.php:42 $activeData = [] → exists() false, tüm erişici alanlar sabit yedek döner (icon→bi-link-45deg, color→#6c757d, ri_icon→ri-link, fa_icon→fas fa-link)
TrafficStatsChannel önbellek öneki TrafficStatsChannel.php:20 'analytics_traffic'
UserStatsChannel önbellek öneki UserStatsChannel.php:18 'analytics_users'
Kanal önbellek ömrü BaseChannel::$cacheTtl = null → "short" (Core/Base/Patterns/BaseChannel.php:27) cache(?int $ttl) ile değiştirilebilir; bu iki kanal cache() çağırmaz → hep varsayılan
Bot tespiti TrafficAnalysisTrait.php:193,206 · WebtrafficController.php:125,129,249 location alanı 'Bot' önekiyle başlar
computeSummary() cihaz dağılımı TrafficAnalysisTrait.php:165,223 ['PC'=>0,'Mobile'=>0,'Tablet'=>0]
top() sınırı TrafficAnalysisTrait.php:267 5
GA4 tarih penceresi (panel) WebtrafficController.php:321 Son 30 gün
saveColors() yetki eşiği RbnAdminService.php:28 can('admin') → AuthRole::ADMIN_ROLES içinde admin seviyesi

5. Tuzaklar

  1. TrafficAnalysisTrait iki sınıfta use edilir → metotlar iki yerde de
    vardır.
    AnalyticsProvider (:20) ve TrafficStatsChannel (:16) aynı trait'i
    kullanır. PHP bir trait'i aynı sınıfta iki kez use etseydi fatal verirdi;
    burada iki farklı sınıf olduğu için derlenir. Sonuç: count(),
    get(), top(), hits() gibi metotların iki uygulaması vardır ve ikisi de
    aynı gövdeyi taşır. Kod değiştirirken her ikisi değiştirilmelidir.

  2. AnalyticsProvider::getDashboardStats() ölü ve ayrıca yanlış.
    (a) Hiçbir yerden çağrılmıyor (grep getDashboardStats → yalnız tanım ve
    Internal/Syshub'ın kendi benzer adlı metodu).
    (b) İçindeki 'today_hits' => $traffic->hits() çağrısı
    TrafficAnalysisTrait::hits()'e düşer (TrafficAnalysisTrait.php:316),
    o da count()'a (:123-132) yani tüm tarihlerin toplamına. Kanal sınıfındaki
    TrafficStatsChannel::hits() ise bugünün toplamını döndürür (:52-58).
    Aynı metot adı, aynı paket, iki farklı anlam. Panel bugün kanalını
    (WebtrafficController ve RbnAdminController → ->traffic()->summary()) kullandığı
    için belki hâlâ doğru çalışıyor; bu satırlara güvenilmemeli.

  3. computeSummary() özyineleme mührü zorunlu. static $isCalculating
    (:139-143) aynı anda ikinci bir çağrı gelirse [] döner, yoksa sonsuz döngü.
    finally (:236-238) mührü her yolda kaldırır; bu blok silinirse kanal
    kalıcı olarak kilitlenir.

  4. TrafficAnalysisTrait::get() üç farklı dönüş şekli döndürür.
    forRange → düz satır dizisi; forDate → o günün dizisi; forTrend →
    ['YYYY-MM-DD' => int] sayım haritası (:100-108, erkenden return ile).
    Tüketici (WebtrafficController::report(), :204) yalnız ilk iki şekli
    bekleyecek şekilde yazılmıştır; forTrend() sonucunu array_filter(fn($hit) => isset($hit['time'])) içinden geçirirse her şeyi düşürür.

  5. TrafficAnalysisTrait durum tutucu — nesne yeniden kullanılamaz.
    query() (:34-43) tüm durumu sıfırlar ama $projectKey sıfırlanmaz
    (:19); withProject() (:24-29) ayrıca $this->storage->traffic()->projectKey
    alanını da mutasyona uğratır — yani paylaşılan depolama durumunu değiştirir.
    Aynı istekte iki farklı proje için trafik sorgusu yapılırsa ilk withProject()
    etkisi kalıcıdır.

  6. AnalyticsProvider::getUserStats() modeli null'a karşı savunmasız.
    $UsersModel = $this->UsersModel (:45) — bu alan #[SubModule]/sihirli
    özellik keşfiyle dolar; BaseProvider bunu garanti etmez. Model yoksa metot
    erken çıkar (:47-53), ama dolu ama yanlış modelde (count()/select()
    çağrılamayan) bir nesne sessizce hata verir.

  7. getStatusDistribution() bilinmeyen durumları yutar. $stats[$row['status']]
    (:74) ile yazılır; $stats yalnız active/inactive/banned/pending ile
    başlatılmıştır (:72). Veritabanında beşinci bir durum varsa dinamik alan
    eklenir — şema ile uyumsuzluk sessizdir.

  8. RbnAdminService::saveColors() istisna atıyor, çağıran yakalamıyor.
    RbnAdminController::saveTheme() (:166-186) try/catch içermez →
    yetkisiz istek 500 + ham hata sayfası döner. Ölçüm: RbnAdminController içinde
    try/catch yok.

  9. SocialMediaProvider durumlu (stateful) nesne. getPlatform() (:40-43)
    $this->activeData'yı üzerine yazar ve $this döndürür. Aynı provider
    örneği üzerinde iki platform üst üste sorulursa ikinci çağrı birincinin
    bağlamını siler (exists() false olur). Bu yüzden RbnAdminService'deki
    allSocialPlatforms() (RbnAdminService.php:53) $this->provider('social') ->all(...) ile dizi dönerken, RbnStudio her platform için ayrı
    getPlatform() çağırır (RbnStudioController.php:286,303) — iki farklı
    kullanım deseni kasıtlıdır.

  10. registerMap() aynı anahtarı iki türe yazar. 'analytics' hem
    services hem providers altında (:37,42). Farklı türler ayrı defterlerde
    tutulduğu için çakışma değildir, ama analytics adı iki anlam taşır.

  11. Önbellek temizleme yolları atlanabiliyor. Trafik özeti önbelleğinin
    (aynı projeye ait api_cpanel_mail önbelleği gibi) bir "temizle" metodu
    RbnAdmin içinde yoktur; getFromCache anahtarı saat/gün bazlı değil,
    durum karması bazlıdır. Trafik özeti "anlık" görünmesi gereken yerde
    (yeni hit) bayat kalabilir — kanıt: AnalyticsService::record() (:40-44)
    yazdıktan sonra hiçbir yerde önbellek düşürülmüyor.

  12. AnalyticsService::getGoogleAnalyticsReports() $type parametresi
    yalnız iki değer kabul ediyor.
    'map' dışındaki her değer standart rapora
    düşer (:56-59); sessizdir.

  13. RbnAdminService::getShareButtons() çıktısı sırasız. $platforms dizisi
    JSON dosyasındaki sırayla gelir (:87 ->all() — varsayılan sıralı),
    ama socialPlatform($key) → provider('social')->getPlatform($key) her
    turda aynı provider örneğinin durumunu değiştirir (tuzak 9).

6. Örnek (gerçek koddan)

Özet istatistiği önbellekten okumak (tüm panel ekranlarının kullandığı yol):

// Bundles/RbnSuite/RbnAdmin/Providers/Fluent/TrafficStatsChannel.php:42-47
public function summary(): array
{
    return $this->getFromCache('summary', function () {
        return $this->computeSummary();
    });
}

ve platform erişiminin akıcı kullanımı:

// Bundles/RbnSuite/RbnStudio/Controllers/RbnStudioController.php:286-293
$meta = $socialProvider ? $socialProvider->getPlatform('instagram') : null;
$platforms['instagram'] = [
    'name'  => $meta && $meta->exists() ? $meta->title() : 'Instagram',
    'icon'  => $meta && $meta->exists() ? $meta->riIcon() : 'ri-instagram-line',
    'color' => $meta && $meta->exists() ? $meta->color() : '#E4405F',
    'badge' => 'Business Media',
    'account_id' => $igAccountId
];

7. İlgili belgeler