folderweb/docs/03-reference/03-template-variables.md
Ruben 76697e4656 Add getting started documentation
Add tutorial on adding content

Add tutorial on styling

Add tutorial on templates

Add configuration reference

Add metadata reference

Add template variables reference

Add internationalization reference

Add plugin system documentation

Add creating templates documentation

Add index page
2025-11-27 23:01:02 +01:00

474 lines
10 KiB
Markdown

# Template Variables Reference
Templates have access to a set of variables provided by FolderWeb and its plugins. This reference documents all available variables and their types.
## Base Template Variables
Available in `base.php`:
### `$content`
The fully rendered HTML content from the page or list template.
**Type:** String (HTML)
**Example:**
```php
<main>
<?= $content ?>
</main>
```
### `$pageTitle`
The page title for the `<title>` tag.
**Type:** String
**Default:** `"FolderWeb"`
**Example:**
```php
<title><?= htmlspecialchars($pageTitle ?? 'FolderWeb') ?></title>
```
**Source:**
1. Language-specific metadata `[lang] title`
2. Root metadata `title`
3. First heading in content
4. Folder name
### `$metaDescription`
SEO description for the `<meta name="description">` tag.
**Type:** String
**Optional:** May be empty
**Example:**
```php
<?php if (!empty($metaDescription)): ?>
<meta name="description" content="<?= htmlspecialchars($metaDescription) ?>">
<?php endif; ?>
```
**Source:**
1. Metadata `search_description`
2. Metadata `summary`
3. Empty if not set
### `$socialImageUrl`
URL to cover image for social media meta tags.
**Type:** String (URL)
**Optional:** May be empty
**Example:**
```php
<?php if (!empty($socialImageUrl)): ?>
<meta property="og:image" content="<?= htmlspecialchars($socialImageUrl) ?>">
<?php endif; ?>
```
**Source:** First `cover.*` image found in content directory
### `$navigation`
Array of navigation menu items.
**Type:** Array of associative arrays
**Structure:**
```php
[
['url' => '/about/', 'title' => 'About'],
['url' => '/blog/', 'title' => 'Blog'],
['url' => '/contact/', 'title' => 'Contact'],
]
```
**Example:**
```php
<?php if (!empty($navigation)): ?>
<nav>
<?php foreach ($navigation as $item): ?>
<a href="<?= htmlspecialchars($item['url']) ?>">
<?= htmlspecialchars($item['title']) ?>
</a>
<?php endforeach; ?>
</nav>
<?php endif; ?>
```
**Source:** Pages with `menu = 1` in metadata, sorted by `menu_order`
### `$homeLabel`
Text for the home link.
**Type:** String
**Default:** `"Home"`
**Example:**
```php
<a href="/"><?= htmlspecialchars($homeLabel ?? 'Home') ?></a>
```
**Source:** Translation string `translations['home']` or fallback "Home"
### `$currentLang`
Current language code.
**Type:** String
**Default:** From `config.ini` `languages.default`
**Example:**
```php
<html lang="<?= htmlspecialchars($currentLang ?? 'en') ?>">
```
**Values:** ISO 639-1 language codes (`en`, `no`, `de`, etc.)
### `$langPrefix`
URL prefix for the current language.
**Type:** String
**Default:** Empty string for default language
**Example:**
```php
<a href="<?= htmlspecialchars($langPrefix ?? '') ?>/">Home</a>
```
**Values:**
- `""` (empty) for default language
- `"/no"` for Norwegian
- `"/de"` for German
- etc.
### `$languageUrls`
URLs to switch between available languages.
**Type:** Associative array
**Structure:**
```php
[
'en' => '/page/',
'no' => '/no/side/',
'de' => '/de/seite/',
]
```
**Example:**
```php
<?php if (!empty($languageUrls) && count($languageUrls) > 1): ?>
<nav class="language-switcher">
<?php foreach ($languageUrls as $lang => $url): ?>
<a href="<?= htmlspecialchars($url) ?>"
<?= ($lang === $currentLang) ? 'aria-current="true"' : '' ?>>
<?= htmlspecialchars(strtoupper($lang)) ?>
</a>
<?php endforeach; ?>
</nav>
<?php endif; ?>
```
### `$translations`
Translated UI strings for the current language.
**Type:** Associative array
**Structure:**
```php
[
'home' => 'Home',
'footer_handcoded' => 'Generated in',
'footer_page_time' => 'ms',
'months' => 'January,February,March,...',
]
```
**Example:**
```php
<p><?= htmlspecialchars($translations['home'] ?? 'Home') ?></p>
```
**Source:** Language files in `custom/languages/[lang].ini` or `app/default/languages/[lang].ini`
### `$pageCssUrl`
URL to page-specific CSS file.
**Type:** String (URL)
**Optional:** Only set if `styles.css` exists in content directory
**Example:**
```php
<?php if (!empty($pageCssUrl)): ?>
<link rel="stylesheet" href="<?= htmlspecialchars($pageCssUrl) ?>?v=<?= htmlspecialchars($pageCssHash ?? '') ?>">
<?php endif; ?>
```
### `$pageCssHash`
MD5 hash of page-specific CSS for cache busting.
**Type:** String (MD5 hash)
**Optional:** Only set if `$pageCssUrl` exists
**Example:** See `$pageCssUrl` above
## Page Template Variables
Available in `page.php`:
### `$content`
The fully rendered HTML content from the page.
**Type:** String (HTML)
**Example:**
```php
<article>
<?= $content ?>
</article>
```
### `$metadata`
All metadata for the current page.
**Type:** Associative array
**Structure:**
```php
[
'title' => 'Page Title',
'summary' => 'Short description',
'date' => '2024-12-15',
'formatted_date' => '15. desember 2024',
'show_date' => true,
'author' => 'Jane Doe', // Custom fields
'tags' => 'web,design',
// ... all other metadata fields
]
```
**Example:**
```php
<?php if (isset($metadata['title'])): ?>
<h1><?= htmlspecialchars($metadata['title']) ?></h1>
<?php endif; ?>
<?php if (isset($metadata['date']) && ($metadata['show_date'] ?? true)): ?>
<time datetime="<?= $metadata['date'] ?>">
<?= $metadata['formatted_date'] ?? $metadata['date'] ?>
</time>
<?php endif; ?>
```
## List Template Variables
Available in `list.php`, `list-grid.php`, `list-compact.php`, etc.:
### `$pageContent`
Optional intro content from the directory's own files.
**Type:** String (HTML)
**Optional:** May be empty
**Example:**
```php
<?php if ($pageContent): ?>
<div class="intro">
<?= $pageContent ?>
</div>
<?php endif; ?>
```
**Source:** Content files in the list directory itself (not subdirectories)
### `$items`
Array of items to display in the list.
**Type:** Array of associative arrays
**Structure:**
```php
[
[
'url' => '/blog/my-post/',
'path' => '/content/blog/2024-12-15-my-post',
'title' => 'My Post',
'summary' => 'Short description',
'date' => '2024-12-15',
'formatted_date' => '15. desember 2024',
'cover_image' => '/blog/my-post/cover.jpg',
// All custom metadata fields...
'author' => 'Jane Doe',
'category' => 'Tutorial',
],
// ... more items
]
```
**Example:**
```php
<?php foreach ($items as $item): ?>
<article>
<?php if (isset($item['cover_image'])): ?>
<img src="<?= $item['cover_image'] ?>"
alt="<?= htmlspecialchars($item['title']) ?>">
<?php endif; ?>
<h2>
<a href="<?= $item['url'] ?>">
<?= htmlspecialchars($item['title']) ?>
</a>
</h2>
<?php if (isset($item['date'])): ?>
<time datetime="<?= $item['date'] ?>">
<?= $item['formatted_date'] ?? $item['date'] ?>
</time>
<?php endif; ?>
<?php if (isset($item['summary'])): ?>
<p><?= htmlspecialchars($item['summary']) ?></p>
<?php endif; ?>
</article>
<?php endforeach; ?>
```
### `$metadata`
Metadata for the list directory itself.
**Type:** Associative array
**Structure:** Same as page metadata
**Example:**
```php
<?php if (isset($metadata['title'])): ?>
<h1><?= htmlspecialchars($metadata['title']) ?></h1>
<?php endif; ?>
```
## Item Properties
Each item in `$items` has these properties:
| Property | Type | Description | Optional |
|----------|------|-------------|----------|
| `url` | String | Full URL to the item | No |
| `path` | String | Filesystem path to item | No |
| `title` | String | Item title | No |
| `summary` | String | Short description | Yes |
| `date` | String | ISO date (YYYY-MM-DD) | Yes |
| `formatted_date` | String | Localized date string | Yes |
| `cover_image` | String | URL to cover image | Yes |
| Custom fields | Mixed | Any metadata fields | Yes |
## Adding Custom Variables
Use the `Hook::TEMPLATE_VARS` hook to add custom variables:
```php
Hooks::add(Hook::TEMPLATE_VARS, function(array $vars, Context $ctx) {
// Add a custom variable
$vars['siteName'] = 'My Website';
// Add computed values
$vars['currentYear'] = date('Y');
// Add from context
$vars['userName'] = $ctx->get('user_name', 'Guest');
return $vars;
});
```
Then use in templates:
```php
<p>&copy; <?= $currentYear ?> <?= htmlspecialchars($siteName) ?></p>
```
## Variable Availability by Template
| Variable | `base.php` | `page.php` | `list.php` |
|----------|------------|------------|------------|
| `$content` | ✓ | ✓ | — |
| `$pageTitle` | ✓ | — | — |
| `$metaDescription` | ✓ | — | — |
| `$socialImageUrl` | ✓ | — | — |
| `$navigation` | ✓ | — | — |
| `$homeLabel` | ✓ | — | — |
| `$currentLang` | ✓ | — | — |
| `$langPrefix` | ✓ | — | — |
| `$languageUrls` | ✓ | — | — |
| `$translations` | ✓ | — | — |
| `$pageCssUrl` | ✓ | — | — |
| `$pageCssHash` | ✓ | — | — |
| `$metadata` | — | ✓ | ✓ |
| `$pageContent` | — | — | ✓ |
| `$items` | — | — | ✓ |
**Note:** All variables are technically available everywhere via plugin hooks, but this table shows the default availability.
## Escaping Output
**Always escape user content** to prevent XSS attacks:
```php
<!-- Good -->
<h1><?= htmlspecialchars($metadata['title']) ?></h1>
<p><?= htmlspecialchars($item['summary']) ?></p>
<!-- Bad -->
<h1><?= $metadata['title'] ?></h1>
<p><?= $item['summary'] ?></p>
```
**Exception:** Already-sanitized HTML like `$content` (rendered from Markdown):
```php
<!-- Good (content is already HTML) -->
<div class="content">
<?= $content ?>
</div>
```
## Checking Variable Existence
Always check if optional variables exist:
```php
<!-- Good -->
<?php if (isset($metadata['author'])): ?>
<p>By <?= htmlspecialchars($metadata['author']) ?></p>
<?php endif; ?>
<!-- Bad (may cause warnings) -->
<p>By <?= htmlspecialchars($metadata['author']) ?></p>
```
Use null coalescing for defaults:
```php
<p><?= htmlspecialchars($metadata['author'] ?? 'Anonymous') ?></p>
```
## Debugging Variables
To see all available variables in a template:
```php
<pre><?php var_dump(get_defined_vars()); ?></pre>
```
Or specific variables:
```php
<pre><?php print_r($metadata); ?></pre>
<pre><?php print_r($items); ?></pre>
```
**Remember to remove debug code** before deploying to production.
## What's Next?
- **[Internationalization](#)** — Use language-specific variables
- **[Creating Plugins](#)** — Add custom template variables
- **[Template Tutorial](#)** — See variables in action