# Fluid Template: Yazım Kuralları

Fluid, TYPO3'ün şablon motorudur. Bu rehber Fluid sözdizimini, ViewHelper'ları ve en iyi uygulamaları kapsar.

---

## Temel Yapı

### Namespace Tanımı

Her Fluid dosyasının başında namespace tanımlanır:

```html
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
      data-namespace-typo3-fluid="true">
```

Özel ViewHelper namespace'i eklemek için (bu projedeki `testproject` örneği):

```html
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
      xmlns:my="http://typo3.org/ns/Gfdhfhgfgg/Testproject/ViewHelpers"
      data-namespace-typo3-fluid="true">
```

---

## Layout, Template, Partial

### Layout

Genel sayfa iskeletini tanımlar. `Resources/Private/Layouts/Default.html`:

```html
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
      data-namespace-typo3-fluid="true">

<f:render partial="Header/Main" arguments="{mainMenu: mainMenu}" />

<main>
    <f:render section="Main" />
</main>

<f:render partial="Footer/Main" />

</html>
```

### Template

Layout'taki section'ları doldurur. `Resources/Private/Templates/Page/Default.html`:

```html
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
      data-namespace-typo3-fluid="true">

<f:layout name="Default" />

<f:section name="Main">
    <div class="content-area">
        <f:format.raw>{content}</f:format.raw>
    </div>
</f:section>

</html>
```

### Partial

Yeniden kullanılabilir bileşenler. `Resources/Private/Partials/Header/Main.html`:

```html
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
      data-namespace-typo3-fluid="true">

<header class="site-header">
    <nav>
        <f:for each="{mainMenu}" as="item">
            <a href="{item.link}" class="{f:if(condition: item.active, then: 'active')}">
                {item.title}
            </a>
        </f:for>
    </nav>
</header>

</html>
```

---

## Değişkenler ve Çıktı

### Değişken Çıktısı

```html
<!-- Basit değişken -->
{variable}

<!-- İç içe nesne -->
{data.title}

<!-- HTML içerik (escape edilmeden) -->
<f:format.raw>{htmlContent}</f:format.raw>

<!-- HTML encode edilmiş -->
<f:format.htmlentitiesDecode>{encodedContent}</f:format.htmlentitiesDecode>
```

### Değişken Tanımlama

```html
<!-- Değişken atama -->
<f:variable name="myVar" value="Merhaba Dünya" />

<!-- Expression ile -->
<f:variable name="fullName" value="{firstName} {lastName}" />

<!-- Hesaplama -->
<f:variable name="total" value="{count + 1}" />
```

---

## Koşullu İfadeler

### f:if

```html
<!-- Basit koşul -->
<f:if condition="{variable}">
    <p>Değişken var!</p>
</f:if>

<!-- if/else -->
<f:if condition="{data.header}">
    <f:then>
        <h2>{data.header}</h2>
    </f:then>
    <f:else>
        <h2>Başlık yok</h2>
    </f:else>
</f:if>

<!-- Karşılaştırma -->
<f:if condition="{data.layout} == 1">
    <div class="layout-one">...</div>
</f:if>

<!-- Çoklu koşul -->
<f:if condition="{data.header} && {data.bodytext}">
    <p>Hem başlık hem içerik var.</p>
</f:if>

<!-- OR koşulu -->
<f:if condition="{data.header} || {data.subheader}">
    <p>Başlık veya alt başlık var.</p>
</f:if>
```

### Inline Koşul

```html
<!-- Ternary operatör -->
<div class="{f:if(condition: data.active, then: 'active', else: 'inactive')}">

<!-- CSS class'ı koşullu ekleme -->
<li class="menu-item {f:if(condition: item.active, then: 'current')}">
```

---

## Döngüler

### f:for

```html
<!-- Basit döngü -->
<f:for each="{items}" as="item">
    <div>{item.title}</div>
</f:for>

<!-- İterasyon bilgisi ile -->
<f:for each="{items}" as="item" iteration="iterator">
    <div class="{f:if(condition: iterator.isFirst, then: 'first')}
                {f:if(condition: iterator.isLast, then: 'last')}
                {f:if(condition: iterator.isEven, then: 'even', else: 'odd')}">
        <span>#{iterator.index + 1}</span>
        <span>{item.title}</span>
    </div>
</f:for>

<!-- Key ile -->
<f:for each="{items}" as="item" key="key">
    <p>{key}: {item}</p>
</f:for>
```

### Iterator Özellikleri

| Özellik | Tip | Açıklama |
|---------|-----|----------|
| `index` | int | 0'dan başlayan sıra |
| `cycle` | int | 1'den başlayan sıra |
| `total` | int | Toplam öğe sayısı |
| `isFirst` | bool | İlk öğe mi? |
| `isLast` | bool | Son öğe mi? |
| `isEven` | bool | Çift sıra mı? |
| `isOdd` | bool | Tek sıra mı? |

---

## Yaygın ViewHelper'lar

### Bağlantılar

```html
<!-- Sayfa bağlantısı -->
<f:link.page pageUid="5">Sayfa Bağlantısı</f:link.page>

<!-- URI oluştur -->
<f:uri.page pageUid="5" />

<!-- Dış bağlantı -->
<f:link.external uri="https://example.com" target="_blank">
    Dış Bağlantı
</f:link.external>

<!-- E-posta bağlantısı -->
<f:link.email email="info@example.com">E-posta</f:link.email>

<!-- Dosya bağlantısı -->
<f:link.typolink parameter="{data.header_link}">
    {data.header}
</f:link.typolink>
```

### Görseller

```html
<!-- Basit resim (bu projede: EXT:testproject) -->
<f:image src="EXT:testproject/Resources/Public/Images/logo.svg"
         alt="Logo" width="200" />

<!-- İşlenmiş resim (resize) -->
<f:image image="{file}" maxWidth="800" alt="{file.alternative}" />

<!-- Media ViewHelper (responsive) -->
<f:media file="{file}" width="800" height="600"
         additionalAttributes="{loading: 'lazy'}" />

<!-- URI oluştur -->
<f:uri.image src="EXT:testproject/Resources/Public/Images/bg.jpg"
             maxWidth="1920" />
```

### Biçimlendirme

```html
<!-- Tarih biçimlendirme -->
<f:format.date format="d.m.Y">{data.crdate}</f:format.date>
<f:format.date format="d F Y" date="now" />

<!-- Sayı biçimlendirme -->
<f:format.number decimals="2" decimalSeparator="," thousandsSeparator=".">
    {price}
</f:format.number>

<!-- Metin kırpma -->
<f:format.crop maxCharacters="150" append="...">{data.bodytext}</f:format.crop>

<!-- HTML temizleme -->
<f:format.stripTags>{htmlContent}</f:format.stripTags>

<!-- nl2br -->
<f:format.nl2br>{multilineText}</f:format.nl2br>

<!-- Raw HTML çıktısı -->
<f:format.raw>{richTextContent}</f:format.raw>
```

### Çeviri

```html
<!-- Dil dosyasından çeviri (bu projede: EXT:testproject) -->
<f:translate key="LLL:EXT:testproject/Resources/Private/Language/locallang.xlf:header.title" />

<!-- Varsayılan değer ile -->
<f:translate key="header.title" extensionName="Testproject" default="Başlık" />

<!-- Argüman ile -->
<f:translate key="welcome.message" arguments="{0: userName}" />
```

---

## Asset ViewHelper'ları (v13)

```html
<!-- CSS dosyası ekle -->
<f:asset.css identifier="my-styles"
             href="EXT:testproject/Resources/Public/Css/layout.css" />

<!-- JavaScript dosyası ekle -->
<f:asset.script identifier="my-script"
                src="EXT:testproject/Resources/Public/JavaScript/main.js"
                defer="true" />

<!-- Inline CSS -->
<f:asset.css identifier="inline-styles">
    .custom-class { color: red; }
</f:asset.css>

<!-- Inline JavaScript -->
<f:asset.script identifier="inline-script">
    console.log('Merhaba TYPO3!');
</f:asset.script>
```

---

## Debug

```html
<!-- Değişkeni debug et -->
<f:debug>{_all}</f:debug>

<!-- Belirli bir değişkeni debug et -->
<f:debug>{data}</f:debug>

<!-- Inline debug -->
{variable -> f:debug()}

<!-- Sadece Development modunda göster -->
<f:if condition="{settings.debug}">
    <f:debug>{_all}</f:debug>
</f:if>
```

---

## Inline Sözdizimi

Fluid'de ViewHelper'lar inline sözdizimi ile de kullanılabilir:

```html
<!-- Tag sözdizimi -->
<f:format.date format="d.m.Y">{date}</f:format.date>

<!-- Inline sözdizimi (pipe operatörü) -->
{date -> f:format.date(format: 'd.m.Y')}

<!-- Zincirleme -->
{data.bodytext -> f:format.stripTags() -> f:format.crop(maxCharacters: 100)}

<!-- Koşullu inline -->
{f:if(condition: variable, then: 'evet', else: 'hayır')}
```

---

## Özel Section ve Render

```html
<!-- Section tanımlama -->
<f:section name="sidebar">
    <aside>
        <h3>Yan Panel</h3>
    </aside>
</f:section>

<!-- Section render etme -->
<f:render section="sidebar" />

<!-- Opsiyonel render -->
<f:render section="sidebar" optional="true" />

<!-- Partial render etme -->
<f:render partial="Components/Card" arguments="{title: 'Başlık', text: 'İçerik'}" />
```

---

## En İyi Uygulamalar

1. **Namespace'i her zaman tanımlayın** — `data-namespace-typo3-fluid="true"` ile
2. **Partial kullanın** — Tekrar eden kodları partial'lara taşıyın
3. **Arguments iletin** — Partial'lara sadece gerekli verileri gönderin
4. **Inline syntax tercih edin** — Basit ifadeler için okunabilirliği artırır
5. **Debug'ı production'da kapatın** — `f:debug` sadece geliştirme ortamında kullanın
6. **format.raw dikkatli kullanın** — XSS riski olabilir, sadece güvenilir içerikle kullanın

---

## Kaynaklar

- [Fluid ViewHelper Reference](https://docs.typo3.org/other/typo3/view-helper-reference/main/en-us/)
- [TYPO3 Fluid Introduction](https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ApiOverview/Fluid/)
