Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions docs/en/appendices/6-0-migration-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -295,3 +295,12 @@ still uses other Diactoros classes or functions, declare
classes and actions using PHP attributes such as `#[Get]`, `#[Post]`, `#[Scope]`,
`#[Resource]`, and more. See [Attribute Routing](../development/attribute-routing)
for full documentation.

### View

- `HtmlString` and the `Cake\View\html()` function wrap trusted markup, while
`HtmlString::render()` escapes ordinary strings and preserves values
implementing the new `HtmlStringable` contract. Supported HtmlHelper and
FormHelper content arguments accept these values without disabling escaping.
See [Rendering Trusted HTML](../views#rendering-trusted-html) for usage and
escaping rules.
27 changes: 27 additions & 0 deletions docs/en/core-libraries/global-constants-and-functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,10 @@ distribute the code), since it's a full emulation wrapper.

Convenience wrapper for `htmlspecialchars()`.

This function also escapes `Cake\View\HtmlStringable` values. To escape
ordinary strings while preserving trusted HTML, use
[`HtmlString::render()`](../views#rendering-trusted-html).

### pluginSplit()

`function` **pluginSplit(string $name, boolean $dotAppend = false, string $plugin = null)**
Expand All @@ -200,6 +204,29 @@ Split the namespace from the classname.

Commonly used like `list($namespace, $className) = namespaceSplit('Cake\Core\App');`

## View Functions

### html()

`function` Cake\\View\\**html(string $html): HtmlString**

Wraps trusted markup in an immutable `Cake\View\HtmlString` value. Import
the namespaced function before using it:

```php
use function Cake\View\html;

echo $this->Html->link(html('<strong>Read more</strong>'), '/articles');
```

This function marks markup as trusted and does not sanitize it. See
[Rendering Trusted HTML](../views#rendering-trusted-html) for escaping rules,
helper support, and custom implementations.

::: info Added in version 6.0.0
The `Cake\View\html()` function was added.
:::

## Core Definition Constants

Most of the following constants refer to paths in your application.
Expand Down
99 changes: 99 additions & 0 deletions docs/en/views.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,105 @@ the `h()` function:
<?= h($user->bio); ?>
```

### Rendering Trusted HTML

When a value can contain either plain text or HTML intended to render directly,
use `Cake\View\HtmlString` to distinguish trusted markup from text that needs
escaping. `HtmlString` is an immutable value object:

```php
use Cake\View\HtmlString;
use function Cake\View\html;

$content = new HtmlString('<strong>Featured article</strong>');

// The html() convenience function creates the same value object.
$content = html('<strong>Featured article</strong>');

echo $content;
// <strong>Featured article</strong>
```

`HtmlString` marks markup as trusted; it does not sanitize it. Only wrap HTML
you control, and escape any untrusted values before including them:

```php
$content = html('<strong>' . h($article->title) . '</strong>');
```

Use `HtmlString::render()` in templates or custom renderers that accept either
a string or an `HtmlStringable` value. It escapes ordinary strings with `h()`
and renders trusted HTML unchanged:

```php
echo HtmlString::render('News & updates');
// News &amp; updates

echo HtmlString::render(html('<strong>News</strong>'));
// <strong>News</strong>
```

An explicit call to `h()` still escapes trusted markup:

```php
echo h(html('<strong>News</strong>'));
// &lt;strong&gt;News&lt;/strong&gt;
```

Casting an `HtmlString` to a string returns its original markup. It also
implements `JsonSerializable`, so `json_encode()` serializes it as a JSON string.

#### Using Trusted HTML with Helpers

The [HtmlHelper](views/helpers/html#creating-links) and
[FormHelper](views/helpers/form#rendering-trusted-html) accept trusted HTML in
supported content arguments without requiring `'escape' => false`:

```php
echo $this->Html->link(html('<strong>Read more</strong>'), '/articles');
// <a href="/articles"><strong>Read more</strong></a>

echo $this->Form->button(html('<em>Save</em>'));
// <button type="submit"><em>Save</em></button>
```

Helper methods still return strings. To pass their output as trusted content
to another helper, wrap it with `html()`. Attribute values continue to be
escaped according to the helper's attribute escaping options.

#### Implementing HtmlStringable

Custom components and plugins can implement `Cake\View\HtmlStringable`
instead of returning an `HtmlString`. The interface extends `Stringable` and
requires a `__toString(): string` method that returns trusted HTML:

```php
use Cake\View\HtmlStringable;

final class Badge implements HtmlStringable
{
public function __construct(private string $label)
{
}

public function __toString(): string
{
return '<span class="badge">' . h($this->label) . '</span>';
}
}

echo HtmlString::render(new Badge('News & updates'));
// <span class="badge">News &amp; updates</span>
```

Implementations are responsible for escaping any untrusted values in their
markup. The contract applies to HTML content, and does not bypass attribute
escaping or explicit calls to `h()`.

::: info Added in version 6.0.0
`HtmlString`, `HtmlStringable`, and `Cake\View\html()` were added.
:::

### Setting View Variables

`method` Cake\\View\\View::**set**(array|string $name, mixed $value = null): static
Expand Down
84 changes: 66 additions & 18 deletions docs/en/views/helpers/form.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,54 @@ re-population and layout. The FormHelper is also flexible - it will do almost
everything for you using conventions, or you can use specific methods to get
only what you need.

## Rendering Trusted HTML

FormHelper accepts [HtmlString](../../views#rendering-trusted-html) and other
`Cake\View\HtmlStringable` values in the following content positions:

- Captions for `button()` and `postButton()`, and content for `postLink()` and
`deleteLink()`.
- Label text for `label()`, the `label` option of `control()`, and the `text`
key of a label options array.
- Option labels for `radio()` and `multiCheckbox()`.
- Explicit error messages passed to `error()` or the `error` option of
`control()`, including individual messages in an array of overrides.

These values render without escaping their markup, while ordinary strings
continue to follow the existing escaping options:

```php
use function Cake\View\html;

echo $this->Form->button(html('<strong>Save</strong>'));

echo $this->Form->control('name', [
'label' => html('<strong>Your name</strong>'),
]);

echo $this->Form->radio('priority', [
['value' => 'high', 'text' => html('<strong>High</strong>')],
['value' => 'normal', 'text' => 'Normal'],
]);

// Override one message while retaining other validation messages.
echo $this->Form->error('name', [
'_empty' => html('<strong>Please enter your name.</strong>'),
]);
```

Only explicit error overrides are treated as trusted HTML. Messages obtained
from the form context, including fallback messages without an override, remain
escaped by default even if they implement `HtmlStringable`.

Wrapping a value does not bypass escaping in attributes, input values,
textarea contents, or select option text. Only wrap markup you control;
`HtmlString` does not sanitize HTML.

::: info Added in version 6.0.0
Support for `HtmlStringable` content was added.
:::

## Starting a Form

`method` Cake\\View\\Helper\\FormHelper::**create**(mixed $context = null, array $options = []): string
Expand Down Expand Up @@ -1833,10 +1881,10 @@ If it was 2009, you would get the following:

## Creating Labels

`method` Cake\\View\\Helper\\FormHelper::**label**(string $fieldName, string $text, array $options): string
`method` Cake\\View\\Helper\\FormHelper::**label**(string $fieldName, HtmlStringable|string|null $text = null, array $options = []): string

- `$fieldName` - A field name in the form `'Modelname.fieldname'`.
- `$text` - An optional string providing the label caption text.
- `$text` - An optional string or `HtmlStringable` value providing the label caption.
- `$options` - Optional. Array containing any of the
[General Control Options](#general-control-options) as well as any valid HTML attributes.

Expand Down Expand Up @@ -1882,7 +1930,7 @@ field errors and when necessary display customized error messages.
`method` Cake\\View\\Helper\\FormHelper::**error**(string $fieldName, mixed $text, array $options): string

- `$fieldName` - A field name in the form `'Modelname.fieldname'`.
- `$text` - Optional. A string or array providing the error message(s). If an
- `$text` - Optional. A string, `HtmlStringable` value, or array providing the error message(s). If an
array, then it should be a hash of key names => messages. Defaults to
`null`.
- `$options` - An optional array that can only contain a boolean with the key
Expand Down Expand Up @@ -2053,15 +2101,15 @@ more complex button content you should use `button()`.

### Creating Button Elements

`method` Cake\\View\\Helper\\FormHelper::**button**(string $title, array $options = []): string
`method` Cake\\View\\Helper\\FormHelper::**button**(HtmlStringable|string $content, array $options = []): string

- `$title` - Mandatory string providing the button's text caption.
- `$content` - Mandatory string or `HtmlStringable` value providing the button's caption.
- `$options` - An optional array including any of the
[General Control Options](#general-control-options), or of the specific button options (see below)
as well as any valid HTML attributes.

Creates an HTML button with the specified title and a default type
of `'button'`.
Creates an HTML button with the specified content and a default type
of `'submit'`.

**Options for Button**

Expand All @@ -2072,9 +2120,9 @@ of `'button'`.
as `submit()` does. This is the default type.
2. `'reset'` - Creates a form reset button.
3. `'button'` - Creates a standard push button.
- `escapeTitle` - Boolean. If set to `true` it will HTML encode
the value provided inside `$title`. Defaults to `true`.
- `escape` - Boolean. If set to `true` it will HTML encode
ordinary strings provided inside `$content`. Defaults to `true`.
- `escapeAttributes` - Boolean. If set to `true` it will HTML encode
all the HTML attributes generated for the button. Defaults to `true`.
- `confirm` - The confirmation message to display on click. Defaults to
`null`.
Expand All @@ -2097,13 +2145,13 @@ Will output:
<button type="submit">Submit Form</button>
```

Example use of the `'escapeTitle'` option:
Example use of the `'escape'` option:

```php
// Will render unescaped HTML.
echo $this->Form->button('<em>Submit Form</em>', [
'type' => 'submit',
'escapeTitle' => false,
'escape' => false,
]);
```

Expand Down Expand Up @@ -2165,10 +2213,10 @@ template option on `FormHelper`.

### Creating POST Buttons

`method` Cake\\View\\Helper\\FormHelper::**postButton**(string $title, mixed $url, array $options = []): string
`method` Cake\\View\\Helper\\FormHelper::**postButton**(HtmlStringable|string $content, array|string $url, array $options = []): string

- `$title` - Mandatory string providing the button's text caption. By default
not HTML encoded.
- `$content` - Mandatory string or `HtmlStringable` value providing the button's
caption. Ordinary strings are HTML encoded by default.
- `$url` - The URL of the form provided as a string or as array.
- `$options` - An optional array including any of the
[General Control Options](#general-control-options), or of the specific options (see below) as well
Expand Down Expand Up @@ -2218,9 +2266,9 @@ inside opened forms.

### Creating POST Links

`method` Cake\\View\\Helper\\FormHelper::**postLink**(string $title, array|string|null $url = null, array $options = []): string
`method` Cake\\View\\Helper\\FormHelper::**postLink**(HtmlStringable|string $content, array|string|null $url = null, array $options = []): string

- `$title` - Mandatory string providing the text to be wrapped in `<a>`
- `$content` - Mandatory string or `HtmlStringable` value to be wrapped in `<a>`
tags.
- `$url` - Optional. String or array which contains the URL
of the form (Cake-relative or external URL starting with `http://`).
Expand Down Expand Up @@ -2269,9 +2317,9 @@ use `Cake\View\Helper\FormHelper::button()` or

### Creating DELETE Links

`method` Cake\\View\\Helper\\FormHelper::**deleteLink**(string $title, array|string|null $url = null, array $options = []): string
`method` Cake\\View\\Helper\\FormHelper::**deleteLink**(HtmlStringable|string $content, array|string|null $url = null, array $options = []): string

- `$title` - Mandatory string providing the text to be wrapped in `<a>`
- `$content` - Mandatory string or `HtmlStringable` value to be wrapped in `<a>`
tags.
- `$url` - Optional. String or array which contains the URL
of the form (Cake-relative or external URL starting with `http://`).
Expand Down
Loading
Loading