folderweb/docs/03-reference/03-template-variables.md

475 lines
10 KiB
Markdown
Raw Normal View History

# 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