Issue #1938972 by msonnabaum, RobLoach, tsphethean, dawehner, rootatwc: Start moving string functions into a utility class.
parent
ec6fa93c2e
commit
d9fd65f900
|
@ -2,6 +2,7 @@
|
|||
|
||||
use Drupal\Component\Utility\NestedArray;
|
||||
use Drupal\Component\Utility\Settings;
|
||||
use Drupal\Component\Utility\String;
|
||||
use Drupal\Component\Utility\Timer;
|
||||
use Drupal\Core\DrupalKernel;
|
||||
use Drupal\Core\Database\Database;
|
||||
|
@ -1558,75 +1559,23 @@ function t($string, array $args = array(), array $options = array()) {
|
|||
/**
|
||||
* Formats a string for HTML display by replacing variable placeholders.
|
||||
*
|
||||
* This function replaces variable placeholders in a string with the requested
|
||||
* values and escapes the values so they can be safely displayed as HTML. It
|
||||
* should be used on any unknown text that is intended to be printed to an HTML
|
||||
* page (especially text that may have come from untrusted users, since in that
|
||||
* case it prevents cross-site scripting and other security problems).
|
||||
*
|
||||
* In most cases, you should use t() rather than calling this function
|
||||
* directly, since it will translate the text (on non-English-only sites) in
|
||||
* addition to formatting it.
|
||||
*
|
||||
* @param $string
|
||||
* A string containing placeholders.
|
||||
* @param $args
|
||||
* An associative array of replacements to make. Occurrences in $string of
|
||||
* any key in $args are replaced with the corresponding value, after optional
|
||||
* sanitization and formatting. The type of sanitization and formatting
|
||||
* depends on the first character of the key:
|
||||
* - @variable: Escaped to HTML using check_plain(). Use this as the default
|
||||
* choice for anything displayed on a page on the site.
|
||||
* - %variable: Escaped to HTML and formatted using drupal_placeholder(),
|
||||
* which makes it display as <em>emphasized</em> text.
|
||||
* - !variable: Inserted as is, with no sanitization or formatting. Only use
|
||||
* this for text that has already been prepared for HTML display (for
|
||||
* example, user-supplied text that has already been run through
|
||||
* check_plain() previously, or is expected to contain some limited HTML
|
||||
* tags and has already been run through filter_xss() previously).
|
||||
*
|
||||
* @see \Drupal\Component\Utility\String::format()
|
||||
* @see t()
|
||||
* @ingroup sanitization
|
||||
*/
|
||||
function format_string($string, array $args = array()) {
|
||||
// Transform arguments before inserting them.
|
||||
foreach ($args as $key => $value) {
|
||||
switch ($key[0]) {
|
||||
case '@':
|
||||
// Escaped only.
|
||||
$args[$key] = check_plain($value);
|
||||
break;
|
||||
|
||||
case '%':
|
||||
default:
|
||||
// Escaped and placeholder.
|
||||
$args[$key] = drupal_placeholder($value);
|
||||
break;
|
||||
|
||||
case '!':
|
||||
// Pass-through.
|
||||
}
|
||||
}
|
||||
return strtr($string, $args);
|
||||
return String::format($string, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes special characters in a plain-text string for display as HTML.
|
||||
*
|
||||
* Also validates strings as UTF-8.
|
||||
*
|
||||
* @param $text
|
||||
* The text to be checked or processed.
|
||||
*
|
||||
* @return
|
||||
* An HTML safe version of $text, or an empty string if $text is not
|
||||
* valid UTF-8.
|
||||
*
|
||||
* @see \Drupal\Component\Utility\String::checkPlain()
|
||||
* @see drupal_validate_utf8()
|
||||
* @ingroup sanitization
|
||||
*/
|
||||
function check_plain($text) {
|
||||
return htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
|
||||
return String::checkPlain($text);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3398,16 +3347,10 @@ function drupal_is_cli() {
|
|||
/**
|
||||
* Formats text for emphasized display in a placeholder inside a sentence.
|
||||
*
|
||||
* Used automatically by format_string().
|
||||
*
|
||||
* @param $text
|
||||
* The text to format (plain-text).
|
||||
*
|
||||
* @return
|
||||
* The formatted text (html).
|
||||
* @see \Drupal\Component\Utility\String::placeholder()
|
||||
*/
|
||||
function drupal_placeholder($text) {
|
||||
return '<em class="placeholder">' . check_plain($text) . '</em>';
|
||||
return String::placeholder($text);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Component\Utility\String.
|
||||
*/
|
||||
|
||||
namespace Drupal\Component\Utility;
|
||||
|
||||
/**
|
||||
* Provides helpers to operate on strings.
|
||||
*/
|
||||
class String {
|
||||
|
||||
/**
|
||||
* Encodes special characters in a plain-text string for display as HTML.
|
||||
*
|
||||
* Also validates strings as UTF-8.
|
||||
*
|
||||
* @param string $text
|
||||
* The text to be checked or processed.
|
||||
*
|
||||
* @return string
|
||||
* An HTML safe version of $text, or an empty string if $text is not
|
||||
* valid UTF-8.
|
||||
*
|
||||
* @see drupal_validate_utf8()
|
||||
* @ingroup sanitization
|
||||
*/
|
||||
public static function checkPlain($text) {
|
||||
return htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a string for HTML display by replacing variable placeholders.
|
||||
*
|
||||
* This function replaces variable placeholders in a string with the requested
|
||||
* values and escapes the values so they can be safely displayed as HTML. It
|
||||
* should be used on any unknown text that is intended to be printed to an HTML
|
||||
* page (especially text that may have come from untrusted users, since in that
|
||||
* case it prevents cross-site scripting and other security problems).
|
||||
*
|
||||
* In most cases, you should use t() rather than calling this function
|
||||
* directly, since it will translate the text (on non-English-only sites) in
|
||||
* addition to formatting it.
|
||||
*
|
||||
* @param $string
|
||||
* A string containing placeholders.
|
||||
* @param $args
|
||||
* An associative array of replacements to make. Occurrences in $string of
|
||||
* any key in $args are replaced with the corresponding value, after optional
|
||||
* sanitization and formatting. The type of sanitization and formatting
|
||||
* depends on the first character of the key:
|
||||
* - @variable: Escaped to HTML using String::checkPlain(). Use this as the
|
||||
* default choice for anything displayed on a page on the site.
|
||||
* - %variable: Escaped to HTML and formatted using String::placeholder(),
|
||||
* which makes it display as <em>emphasized</em> text.
|
||||
* - !variable: Inserted as is, with no sanitization or formatting. Only use
|
||||
* this for text that has already been prepared for HTML display (for
|
||||
* example, user-supplied text that has already been run through
|
||||
* String::checkPlain() previously, or is expected to contain some limited
|
||||
* HTML tags and has already been run through filter_xss() previously).
|
||||
*
|
||||
*
|
||||
* @see t()
|
||||
* @ingroup sanitization
|
||||
*
|
||||
* @return mixte
|
||||
* The formatted string with placeholders inserted, or FALSE if no args specified.
|
||||
*/
|
||||
public static function format($string, array $args = array()) {
|
||||
// Transform arguments before inserting them.
|
||||
foreach ($args as $key => $value) {
|
||||
switch ($key[0]) {
|
||||
case '@':
|
||||
// Escaped only.
|
||||
$args[$key] = static::checkPlain($value);
|
||||
break;
|
||||
|
||||
case '%':
|
||||
default:
|
||||
// Escaped and placeholder.
|
||||
$args[$key] = static::placeholder($value);
|
||||
break;
|
||||
|
||||
case '!':
|
||||
// Pass-through.
|
||||
}
|
||||
}
|
||||
return strtr($string, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats text for emphasized display in a placeholder inside a sentence.
|
||||
*
|
||||
* Used automatically by self::format().
|
||||
*
|
||||
* @param string $text
|
||||
* The text to format (plain-text).
|
||||
*
|
||||
* @return string
|
||||
* The formatted text (html).
|
||||
*/
|
||||
public static function placeholder($text) {
|
||||
return '<em class="placeholder">' . static::checkPlain($text) . '</em>';
|
||||
}
|
||||
|
||||
}
|
|
@ -10,7 +10,7 @@ namespace Drupal\system\Tests\Common;
|
|||
use Drupal\simpletest\DrupalUnitTestBase;
|
||||
|
||||
/**
|
||||
* Tests for check_plain(), filter_xss(), format_string(), and check_url().
|
||||
* Tests for filter_xss() and check_url().
|
||||
*/
|
||||
class XssUnitTest extends DrupalUnitTestBase {
|
||||
|
||||
|
@ -24,7 +24,7 @@ class XssUnitTest extends DrupalUnitTestBase {
|
|||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'String filtering tests',
|
||||
'description' => 'Confirm that check_plain(), filter_xss(), format_string() and check_url() work correctly, including invalid multi-byte sequences.',
|
||||
'description' => 'Confirm that filter_xss() and check_url() work correctly, including invalid multi-byte sequences.',
|
||||
'group' => 'Common',
|
||||
);
|
||||
}
|
||||
|
@ -38,14 +38,6 @@ class XssUnitTest extends DrupalUnitTestBase {
|
|||
* Checks that invalid multi-byte sequences are rejected.
|
||||
*/
|
||||
function testInvalidMultiByte() {
|
||||
// Ignore PHP 5.3+ invalid multibyte sequence warning.
|
||||
$text = @check_plain("Foo\xC0barbaz");
|
||||
$this->assertEqual($text, '', 'check_plain() rejects invalid sequence "Foo\xC0barbaz"');
|
||||
// Ignore PHP 5.3+ invalid multibyte sequence warning.
|
||||
$text = @check_plain("\xc2\"");
|
||||
$this->assertEqual($text, '', 'check_plain() rejects invalid sequence "\xc2\""');
|
||||
$text = check_plain("Fooÿñ");
|
||||
$this->assertEqual($text, "Fooÿñ", 'check_plain() accepts valid sequence "Fooÿñ"');
|
||||
$text = filter_xss("Foo\xC0barbaz");
|
||||
$this->assertEqual($text, '', 'filter_xss() rejects invalid sequence "Foo\xC0barbaz"');
|
||||
$text = filter_xss("Fooÿñ");
|
||||
|
@ -53,29 +45,17 @@ class XssUnitTest extends DrupalUnitTestBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Checks that special characters are escaped.
|
||||
* Tests t() functionality.
|
||||
*/
|
||||
function testEscaping() {
|
||||
$text = check_plain("<script>");
|
||||
$this->assertEqual($text, '<script>', 'check_plain() escapes <script>');
|
||||
$text = check_plain('<>&"\'');
|
||||
$this->assertEqual($text, '<>&"'', 'check_plain() escapes reserved HTML characters.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests t() and format_string() replacement functionality.
|
||||
*/
|
||||
function testFormatStringAndT() {
|
||||
foreach (array('format_string', 't') as $function) {
|
||||
$text = $function('Simple text');
|
||||
$this->assertEqual($text, 'Simple text', $function . ' leaves simple text alone.');
|
||||
$text = $function('Escaped text: @value', array('@value' => '<script>'));
|
||||
$this->assertEqual($text, 'Escaped text: <script>', $function . ' replaces and escapes string.');
|
||||
$text = $function('Placeholder text: %value', array('%value' => '<script>'));
|
||||
$this->assertEqual($text, 'Placeholder text: <em class="placeholder"><script></em>', $function . ' replaces, escapes and themes string.');
|
||||
$text = $function('Verbatim text: !value', array('!value' => '<script>'));
|
||||
$this->assertEqual($text, 'Verbatim text: <script>', $function . ' replaces verbatim string as-is.');
|
||||
}
|
||||
function testT() {
|
||||
$text = t('Simple text');
|
||||
$this->assertEqual($text, 'Simple text', 't leaves simple text alone.');
|
||||
$text = t('Escaped text: @value', array('@value' => '<script>'));
|
||||
$this->assertEqual($text, 'Escaped text: <script>', 't replaces and escapes string.');
|
||||
$text = t('Placeholder text: %value', array('%value' => '<script>'));
|
||||
$this->assertEqual($text, 'Placeholder text: <em class="placeholder"><script></em>', 't replaces, escapes and themes string.');
|
||||
$text = t('Verbatim text: !value', array('!value' => '<script>'));
|
||||
$this->assertEqual($text, 'Verbatim text: <script>', 't replaces verbatim string as-is.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Component\Utility\StringTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Component\Utility;
|
||||
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\Component\Utility\String;
|
||||
|
||||
/**
|
||||
* Tests string filtering.
|
||||
*
|
||||
* @see \Drupal\Component\Utility\String
|
||||
*/
|
||||
class StringTest extends UnitTestCase {
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'String filtering tests',
|
||||
'description' => 'Confirm that String::checkPlain() and String::format() work correctly, including invalid multi-byte sequences.',
|
||||
'group' => 'Common',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests String::checkPlain().
|
||||
*
|
||||
* @dataProvider providerCheckPlain
|
||||
*
|
||||
* @param string $text
|
||||
* The text to provide to String::checkPlain().
|
||||
* @param string $expected
|
||||
* The expected output from the function.
|
||||
* @param string $message
|
||||
* The message to provide as output for the test.
|
||||
* @param bool $ignorewarnings
|
||||
* Whether or not to ignore PHP 5.3+ invalid multibyte sequence warnings.
|
||||
*/
|
||||
function testCheckPlain($text, $expected, $message, $ignorewarnings = FALSE) {
|
||||
$result = $ignorewarnings ? @String::checkPlain($text) : String::checkPlain($text);
|
||||
$this->assertEquals($result, $expected, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testCheckPlain().
|
||||
*
|
||||
* @see testCheckPlain()
|
||||
*/
|
||||
function providerCheckPlain() {
|
||||
// Checks that invalid multi-byte sequences are rejected.
|
||||
$tests[] = array("Foo\xC0barbaz", '', 'String::checkPlain() rejects invalid sequence "Foo\xC0barbaz"', TRUE);
|
||||
$tests[] = array("\xc2\"", '', 'String::checkPlain() rejects invalid sequence "\xc2\""', TRUE);
|
||||
$tests[] = array("Fooÿñ", "Fooÿñ", 'String::checkPlain() accepts valid sequence "Fooÿñ"');
|
||||
|
||||
// Checks that special characters are escaped.
|
||||
$tests[] = array("<script>", '<script>', 'String::checkPlain() escapes <script>');
|
||||
$tests[] = array('<>&"\'', '<>&"'', 'String::checkPlain() escapes reserved HTML characters.');
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests string formatting with String::format().
|
||||
*
|
||||
* @dataProvider providerFormat
|
||||
*
|
||||
* @param string $string
|
||||
* The string to run through String::format().
|
||||
* @param string $args
|
||||
* The arguments to pass into String::format().
|
||||
* @param string $expected
|
||||
* The expected result from calling the function.
|
||||
* @param string $message
|
||||
* The message to display as output to the test.
|
||||
*
|
||||
* @see String::format()
|
||||
*/
|
||||
function testFormat($string, $args, $expected, $message) {
|
||||
$result = String::format($string, $args);
|
||||
$this->assertEquals($result, $expected, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testFormat().
|
||||
*
|
||||
* @see testFormat()
|
||||
*/
|
||||
function providerFormat() {
|
||||
$tests[] = array('Simple text', array(), 'Simple text', 'String::format leaves simple text alone.');
|
||||
$tests[] = array('Escaped text: @value', array('@value' => '<script>'), 'Escaped text: <script>', 'String::format replaces and escapes string.');
|
||||
$tests[] = array('Placeholder text: %value', array('%value' => '<script>'), 'Placeholder text: <em class="placeholder"><script></em>', 'String::format replaces, escapes and themes string.');
|
||||
$tests[] = array('Verbatim text: !value', array('!value' => '<script>'), 'Verbatim text: <script>', 'String::format replaces verbatim string as-is.');
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests String::placeholder().
|
||||
*
|
||||
* @see String::placeholder()
|
||||
*/
|
||||
function testPlaceholder() {
|
||||
$this->assertEquals('<em class="placeholder">Some text</em>', String::placeholder('Some text'));
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue