protected static FormattableMarkup::placeholderFormat($string, array $args)
Replaces placeholders in a string with values.
Parameters
string $string: A string containing placeholders. The string itself is expected to be safe and correct HTML. Any unsafe content must be in $args and inserted via placeholders.
array $args: An associative array of replacements. Each array key should be the same as a placeholder in $string. The corresponding value should be a string or an object that implements \Drupal\Component\Render\MarkupInterface. The value replaces the placeholder in $string. Sanitization and formatting will be done before replacement. The type of sanitization and formatting depends on the first character of the key:
-
@variable: When the placeholder replacement value is:
- A string, the replaced value in the returned string will be sanitized using \Drupal\Component\Utility\Html::escape().
- A MarkupInterface object, the replaced value in the returned string will not be sanitized.
- A MarkupInterface object cast to a string, the replaced value in the returned string be forcibly sanitized using \Drupal\Component\Utility\Html::escape().
1 | $this ->placeholderFormat( 'This will force HTML-escaping of the replacement value: @text' , [ '@text' => (string) $safe_string_interface_object )); |
Use this placeholder as the default choice for anything displayed on the site, but not within HTML attributes, JavaScript, or CSS. Doing so is a security risk.
- %variable: Use when the replacement value is to be wrapped in <em> tags. A call like:
1 2 3 | $string = "%output_text" ; $arguments = [ 'output_text' => 'text output here.' ]; $this ->placeholderFormat( $string , $arguments ); |
makes the following HTML code:
1 | <em class = "placeholder" >text output here.em> |
As with @variable, do not use this within HTML attributes, JavaScript, or CSS. Doing so is a security risk.
- :variable: Return value is escaped with \Drupal\Component\Utility\Html::escape() and filtered for dangerous protocols using UrlHelper::stripDangerousProtocols(). Use this when using the "href" attribute, ensuring the attribute value is always wrapped in quotes:
1 2 3 4 | // Secure (with quotes): $this ->placeholderFormat( '<a href=":url">@variable</a>' , [ ':url' => $url , '@variable' => $variable ]); // Insecure (without quotes): $this ->placeholderFormat( '<a href=:url>@variable</a>' , [ ':url' => $url , '@variable' => $variable ]); |
When ":variable" comes from arbitrary user input, the result is secure, but not guaranteed to be a valid URL (which means the resulting output could fail HTML validation). To guarantee a valid URL, use Url::fromUri($user_input)->toString() (which either throws an exception or returns a well-formed URL) before passing the result into a ":variable" placeholder.
Return value
string A formatted HTML string with the placeholders replaced.
See also
\Drupal\Core\StringTranslation\TranslatableMarkup
\Drupal\Core\StringTranslation\PluralTranslatableMarkup
\Drupal\Component\Utility\Html::escape()
\Drupal\Component\Utility\UrlHelper::stripDangerousProtocols()
Related topics
- Sanitization functions
- Functions to sanitize values.
File
- core/lib/Drupal/Component/Render/FormattableMarkup.php, line 188
Class
- FormattableMarkup
- Formats a string for HTML display by replacing variable placeholders.
Namespace
Drupal\Component\Render
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | protected static function placeholderFormat( $string , array $args ) { // Transform arguments before inserting them. foreach ( $args as $key => $value ) { switch ( $key [0]) { case '@' : // Escape if the value is not an object from a class that implements // \Drupal\Component\Render\MarkupInterface, for example strings will // be escaped. // Strings that are safe within HTML fragments, but not within other // contexts, may still be an instance of // \Drupal\Component\Render\MarkupInterface, so this placeholder type // must not be used within HTML attributes, JavaScript, or CSS. $args [ $key ] = static ::placeholderEscape( $value ); break ; case ':' : // Strip URL protocols that can be XSS vectors. $value = UrlHelper::stripDangerousProtocols( $value ); // Escape unconditionally, without checking whether the value is an // instance of \Drupal\Component\Render\MarkupInterface. This forces // characters that are unsafe for use in an "href" HTML attribute to // be encoded. If a caller wants to pass a value that is extracted // from HTML and therefore is already HTML encoded, it must invoke // \Drupal\Component\Render\OutputStrategyInterface::renderFromHtml() // on it prior to passing it in as a placeholder value of this type. // @todo Add some advice and stronger warnings. $args [ $key ] = Html::escape( $value ); break ; case '%' : // Similarly to @, escape non-safe values. Also, add wrapping markup // in order to render as a placeholder. Not for use within attributes, // per the warning above about // \Drupal\Component\Render\MarkupInterface and also due to the // wrapping markup. $args [ $key ] = '<em class="placeholder">' . static ::placeholderEscape( $value ) . '</em>' ; break ; default : // We do not trigger an error for placeholder that start with an // alphabetic character. // @todo https://www.drupal.org/node/2807743 Change to an exception // and always throw regardless of the first character. if (!ctype_alpha( $key [0])) { // We trigger an error as we may want to introduce new placeholders // in the future without breaking backward compatibility. trigger_error( 'Invalid placeholder (' . $key . ') in string: ' . $string , E_USER_ERROR); } elseif ( strpos ( $string , $key ) !== FALSE) { trigger_error( 'Invalid placeholder (' . $key . ') in string: ' . $string , E_USER_DEPRECATED); } // No replacement possible therefore we can discard the argument. unset( $args [ $key ]); break ; } } return strtr ( $string , $args ); } |
Please login to continue.