Merge branch '2.4'
* 2.4: Lower mbstring dependency [Console]Improve formatter for double-width character Lower mbstring dep, remove it for Yaml and CssSelector components [Security] Add check for supported attributes in AclVoter [Form] Fixed TrimListenerTest as of PHP 5.5 Added more IDE links [DependencyInjection] Fix parameter description in ConfigurationExtensionInterface [Security] fixed wrong PHPDoc of the TokenGeneratorInterface [Finder] fixed typehint of the Finder::addAdapter() method [TwigBridge][Transchoice] set %count% from the current context. [DependencyInjection] Fix travis unit tests Update PHPUnit before run [Validator] fixed wrong test [WebProfilerBundle] added test case for #10773 [WebProfilerBundle] fixed profiler homepage, fixed #10806 [WebProfilerBundle] Added test case for #10806 changed travis to run on the nightly builds of HHVM until everything gets stable Fixed issue #5427 Allow URLs that don't contain a path Conflicts: .travis.yml src/Symfony/Component/Console/Application.php
This commit is contained in:
commit
7e4b4a7ebb
15
.travis.yml
15
.travis.yml
@ -6,23 +6,24 @@ php:
|
|||||||
- 5.4
|
- 5.4
|
||||||
- 5.5
|
- 5.5
|
||||||
- 5.6
|
- 5.6
|
||||||
- hhvm
|
- hhvm-nightly
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
allow_failures:
|
allow_failures:
|
||||||
- php: hhvm
|
- php: hhvm-nightly
|
||||||
|
|
||||||
services: mongodb
|
services: mongodb
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- travis_retry sudo apt-get install parallel
|
- travis_retry sudo apt-get install parallel
|
||||||
- sh -c 'if [ "$TRAVIS_PHP_VERSION" != "hhvm" ]; then echo "" >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini; fi;'
|
- sh -c 'if [ "$TRAVIS_PHP_VERSION" != "hhvm-nightly" ]; then echo "" >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini; fi;'
|
||||||
- sh -c 'if [ "$TRAVIS_PHP_VERSION" != "hhvm" ]; then echo "extension = mongo.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; fi;'
|
- sh -c 'if [ "$TRAVIS_PHP_VERSION" != "hhvm-nightly" ]; then echo "extension = mongo.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; fi;'
|
||||||
- sh -c 'if [ "$TRAVIS_PHP_VERSION" != "hhvm" ] && [ $(php -r "echo PHP_MINOR_VERSION;") -le 4 ]; then echo "extension = apc.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; fi;'
|
- sh -c 'if [ "$TRAVIS_PHP_VERSION" != "hhvm-nightly" ] && [ $(php -r "echo PHP_MINOR_VERSION;") -le 4 ]; then echo "extension = apc.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; fi;'
|
||||||
- sh -c 'if [ "$TRAVIS_PHP_VERSION" != "hhvm" ]; then echo "extension = memcached.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; fi;'
|
- sh -c 'if [ "$TRAVIS_PHP_VERSION" != "hhvm-nightly" ]; then echo "extension = memcached.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; fi;'
|
||||||
- sh -c 'if [ "$TRAVIS_PHP_VERSION" != "hhvm" ]; then echo "extension = memcache.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; fi;'
|
- sh -c 'if [ "$TRAVIS_PHP_VERSION" != "hhvm-nightly" ]; then echo "extension = memcache.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; fi;'
|
||||||
- sudo locale-gen fr_FR.UTF-8 && sudo update-locale
|
- sudo locale-gen fr_FR.UTF-8 && sudo update-locale
|
||||||
- COMPOSER_ROOT_VERSION=dev-master composer --prefer-source --dev install
|
- COMPOSER_ROOT_VERSION=dev-master composer --prefer-source --dev install
|
||||||
|
- wget https://phar.phpunit.de/phpunit.phar && rm `which phpunit` && sudo cp phpunit.phar /usr/local/bin/phpunit && sudo chmod +x /usr/local/bin/phpunit
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- ls -d src/Symfony/*/* | parallel --gnu --keep-order 'echo "Running {} tests"; phpunit --exclude-group tty,benchmark {};' || exit 1
|
- ls -d src/Symfony/*/* | parallel --gnu --keep-order 'echo "Running {} tests"; phpunit --exclude-group tty,benchmark {};' || exit 1
|
||||||
|
@ -98,11 +98,15 @@ class TransNode extends \Twig_Node
|
|||||||
foreach ($matches[1] as $var) {
|
foreach ($matches[1] as $var) {
|
||||||
$key = new \Twig_Node_Expression_Constant('%'.$var.'%', $body->getLine());
|
$key = new \Twig_Node_Expression_Constant('%'.$var.'%', $body->getLine());
|
||||||
if (!$vars->hasElement($key)) {
|
if (!$vars->hasElement($key)) {
|
||||||
|
if ('count' === $var) {
|
||||||
|
$vars->addElement($this->getNode('count'), $key);
|
||||||
|
} else {
|
||||||
$varExpr = new \Twig_Node_Expression_Name($var, $body->getLine());
|
$varExpr = new \Twig_Node_Expression_Name($var, $body->getLine());
|
||||||
$varExpr->setAttribute('ignore_strict_check', $ignoreStrictCheck);
|
$varExpr->setAttribute('ignore_strict_check', $ignoreStrictCheck);
|
||||||
$vars->addElement($varExpr, $key);
|
$vars->addElement($varExpr, $key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return array(new \Twig_Node_Expression_Constant(str_replace('%%', '%', trim($msg)), $body->getLine()), $vars);
|
return array(new \Twig_Node_Expression_Constant(str_replace('%%', '%', trim($msg)), $body->getLine()), $vars);
|
||||||
}
|
}
|
||||||
|
@ -96,6 +96,8 @@ class TranslationExtensionTest extends \PHPUnit_Framework_TestCase
|
|||||||
'There is 5 apples (Symfony2)', array('count' => 5)),
|
'There is 5 apples (Symfony2)', array('count' => 5)),
|
||||||
array('{% transchoice count into "fr"%}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples{% endtranschoice %}',
|
array('{% transchoice count into "fr"%}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples{% endtranschoice %}',
|
||||||
'There is no apples', array('count' => 0)),
|
'There is no apples', array('count' => 0)),
|
||||||
|
array('{% transchoice 5 into "fr"%}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples{% endtranschoice %}',
|
||||||
|
'There is 5 apples'),
|
||||||
|
|
||||||
// trans filter
|
// trans filter
|
||||||
array('{{ "Hello"|trans }}', 'Hello'),
|
array('{{ "Hello"|trans }}', 'Hello'),
|
||||||
|
@ -208,12 +208,8 @@ abstract class Descriptor implements DescriptorInterface
|
|||||||
if (is_bool($value) || is_array($value) || (null === $value)) {
|
if (is_bool($value) || is_array($value) || (null === $value)) {
|
||||||
$jsonString = json_encode($value);
|
$jsonString = json_encode($value);
|
||||||
|
|
||||||
if (!function_exists('mb_strlen')) {
|
if (preg_match('/^(.{60})./us', $jsonString, $matches)) {
|
||||||
return substr($jsonString, 0, 60).(strlen($jsonString) > 60 ? ' ...' : '');
|
return $matches[1].'...';
|
||||||
}
|
|
||||||
|
|
||||||
if (mb_strlen($jsonString) > 60) {
|
|
||||||
return mb_substr($jsonString, 0, 60).' ...';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $jsonString;
|
return $jsonString;
|
||||||
|
@ -421,6 +421,8 @@ class FrameworkExtension extends Extension
|
|||||||
$links = array(
|
$links = array(
|
||||||
'textmate' => 'txmt://open?url=file://%%f&line=%%l',
|
'textmate' => 'txmt://open?url=file://%%f&line=%%l',
|
||||||
'macvim' => 'mvim://open?url=file://%%f&line=%%l',
|
'macvim' => 'mvim://open?url=file://%%f&line=%%l',
|
||||||
|
'emacs' => 'emacs://open?url=file://%file&line=%line',
|
||||||
|
'sublime' => 'subl://open?url=file://%file&line=%line',
|
||||||
);
|
);
|
||||||
|
|
||||||
$container->setParameter('templating.helper.code.file_link_format', isset($links[$ide]) ? $links[$ide] : $ide);
|
$container->setParameter('templating.helper.code.file_link_format', isset($links[$ide]) ? $links[$ide] : $ide);
|
||||||
|
@ -232,7 +232,7 @@ class ProfilerController
|
|||||||
$session->getFlashBag()->setAll($session->getFlashBag()->peekAll());
|
$session->getFlashBag()->setAll($session->getFlashBag()->peekAll());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (null === $token) {
|
if ('empty' === $token || null === $token) {
|
||||||
return new Response('', 200, array('Content-Type' => 'text/html'));
|
return new Response('', 200, array('Content-Type' => 'text/html'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,77 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Bundle\WebProfilerBundle\Tests\Controller;
|
||||||
|
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
|
||||||
|
use Symfony\Bundle\WebProfilerBundle\Controller\ProfilerController;
|
||||||
|
use Symfony\Component\HttpKernel\Profiler\Profile;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
|
||||||
|
class ProfilerControllerTest extends TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @dataProvider getEmptyTokenCases
|
||||||
|
*/
|
||||||
|
public function testEmptyToken($token)
|
||||||
|
{
|
||||||
|
$urlGenerator = $this->getMock('Symfony\Component\Routing\Generator\UrlGeneratorInterface');
|
||||||
|
$twig = $this->getMock('Twig_Environment');
|
||||||
|
$profiler = $this
|
||||||
|
->getMockBuilder('Symfony\Component\HttpKernel\Profiler\Profiler')
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->getMock();
|
||||||
|
|
||||||
|
$controller = new ProfilerController($urlGenerator, $profiler, $twig, array());
|
||||||
|
|
||||||
|
$response = $controller->toolbarAction(Request::create('/_wdt/empty'), $token);
|
||||||
|
$this->assertEquals(200, $response->getStatusCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEmptyTokenCases()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array(null),
|
||||||
|
// "empty" is also a valid empty token case, see https://github.com/symfony/symfony/issues/10806
|
||||||
|
array('empty'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testReturns404onTokenNotFound()
|
||||||
|
{
|
||||||
|
$urlGenerator = $this->getMock('Symfony\Component\Routing\Generator\UrlGeneratorInterface');
|
||||||
|
$twig = $this->getMock('Twig_Environment');
|
||||||
|
$profiler = $this
|
||||||
|
->getMockBuilder('Symfony\Component\HttpKernel\Profiler\Profiler')
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->getMock();
|
||||||
|
|
||||||
|
$controller = new ProfilerController($urlGenerator, $profiler, $twig, array());
|
||||||
|
|
||||||
|
$profiler
|
||||||
|
->expects($this->exactly(2))
|
||||||
|
->method('loadProfile')
|
||||||
|
->will($this->returnCallback(function ($token) {
|
||||||
|
if ('found' == $token) {
|
||||||
|
return new Profile($token);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}))
|
||||||
|
;
|
||||||
|
|
||||||
|
$response = $controller->toolbarAction(Request::create('/_wdt/found'), 'found');
|
||||||
|
$this->assertEquals(200, $response->getStatusCode());
|
||||||
|
|
||||||
|
$response = $controller->toolbarAction(Request::create('/_wdt/notFound'), 'notFound');
|
||||||
|
$this->assertEquals(404, $response->getStatusCode());
|
||||||
|
}
|
||||||
|
}
|
@ -152,12 +152,12 @@ class Cookie
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (null !== $url) {
|
if (null !== $url) {
|
||||||
if ((false === $urlParts = parse_url($url)) || !isset($urlParts['host']) || !isset($urlParts['path'])) {
|
if ((false === $urlParts = parse_url($url)) || !isset($urlParts['host'])) {
|
||||||
throw new \InvalidArgumentException(sprintf('The URL "%s" is not valid.', $url));
|
throw new \InvalidArgumentException(sprintf('The URL "%s" is not valid.', $url));
|
||||||
}
|
}
|
||||||
|
|
||||||
$values['domain'] = $urlParts['host'];
|
$values['domain'] = $urlParts['host'];
|
||||||
$values['path'] = substr($urlParts['path'], 0, strrpos($urlParts['path'], '/'));
|
$values['path'] = isset($urlParts['path']) ? substr($urlParts['path'], 0, strrpos($urlParts['path'], '/')) : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($parts as $part) {
|
foreach ($parts as $part) {
|
||||||
|
@ -75,6 +75,8 @@ class CookieTest extends \PHPUnit_Framework_TestCase
|
|||||||
public function testFromStringWithUrl()
|
public function testFromStringWithUrl()
|
||||||
{
|
{
|
||||||
$this->assertEquals('foo=bar; domain=www.example.com; path=/', (string) Cookie::FromString('foo=bar', 'http://www.example.com/'));
|
$this->assertEquals('foo=bar; domain=www.example.com; path=/', (string) Cookie::FromString('foo=bar', 'http://www.example.com/'));
|
||||||
|
$this->assertEquals('foo=bar; domain=www.example.com; path=/', (string) Cookie::FromString('foo=bar', 'http://www.example.com'));
|
||||||
|
$this->assertEquals('foo=bar; domain=www.example.com; path=/', (string) Cookie::FromString('foo=bar', 'http://www.example.com?foo'));
|
||||||
$this->assertEquals('foo=bar; domain=www.example.com; path=/foo', (string) Cookie::FromString('foo=bar', 'http://www.example.com/foo/bar'));
|
$this->assertEquals('foo=bar; domain=www.example.com; path=/foo', (string) Cookie::FromString('foo=bar', 'http://www.example.com/foo/bar'));
|
||||||
$this->assertEquals('foo=bar; domain=www.example.com; path=/', (string) Cookie::FromString('foo=bar; path=/', 'http://www.example.com/foo/bar'));
|
$this->assertEquals('foo=bar; domain=www.example.com; path=/', (string) Cookie::FromString('foo=bar; path=/', 'http://www.example.com/foo/bar'));
|
||||||
$this->assertEquals('foo=bar; domain=www.myotherexample.com; path=/', (string) Cookie::FromString('foo=bar; domain=www.myotherexample.com', 'http://www.example.com/'));
|
$this->assertEquals('foo=bar; domain=www.myotherexample.com; path=/', (string) Cookie::FromString('foo=bar; domain=www.myotherexample.com', 'http://www.example.com/'));
|
||||||
|
@ -682,21 +682,11 @@ class Application
|
|||||||
*/
|
*/
|
||||||
public function renderException($e, $output)
|
public function renderException($e, $output)
|
||||||
{
|
{
|
||||||
$strlen = function ($string) {
|
|
||||||
if (!function_exists('mb_strlen')) {
|
|
||||||
return strlen($string);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (false === $encoding = mb_detect_encoding($string)) {
|
|
||||||
return strlen($string);
|
|
||||||
}
|
|
||||||
|
|
||||||
return mb_strlen($string, $encoding);
|
|
||||||
};
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
$title = sprintf(' [%s] ', get_class($e));
|
$title = sprintf(' [%s] ', get_class($e));
|
||||||
$len = $strlen($title);
|
|
||||||
|
$len = $this->stringWidth($title);
|
||||||
|
|
||||||
$width = $this->getTerminalWidth() ? $this->getTerminalWidth() - 1 : PHP_INT_MAX;
|
$width = $this->getTerminalWidth() ? $this->getTerminalWidth() - 1 : PHP_INT_MAX;
|
||||||
// HHVM only accepts 32 bits integer in str_split, even when PHP_INT_MAX is a 64 bit integer: https://github.com/facebook/hhvm/issues/1327
|
// HHVM only accepts 32 bits integer in str_split, even when PHP_INT_MAX is a 64 bit integer: https://github.com/facebook/hhvm/issues/1327
|
||||||
if (defined('HHVM_VERSION') && $width > 1 << 31) {
|
if (defined('HHVM_VERSION') && $width > 1 << 31) {
|
||||||
@ -705,9 +695,9 @@ class Application
|
|||||||
$formatter = $output->getFormatter();
|
$formatter = $output->getFormatter();
|
||||||
$lines = array();
|
$lines = array();
|
||||||
foreach (preg_split('/\r?\n/', $e->getMessage()) as $line) {
|
foreach (preg_split('/\r?\n/', $e->getMessage()) as $line) {
|
||||||
foreach (str_split($line, $width - 4) as $line) {
|
foreach ($this->splitStringByWidth($line, $width - 4) as $line) {
|
||||||
// pre-format lines to get the right string length
|
// pre-format lines to get the right string length
|
||||||
$lineLength = $strlen(preg_replace('/\[[^m]*m/', '', $formatter->format($line))) + 4;
|
$lineLength = $this->stringWidth(preg_replace('/\[[^m]*m/', '', $formatter->format($line))) + 4;
|
||||||
$lines[] = array($line, $lineLength);
|
$lines[] = array($line, $lineLength);
|
||||||
|
|
||||||
$len = max($lineLength, $len);
|
$len = max($lineLength, $len);
|
||||||
@ -716,7 +706,7 @@ class Application
|
|||||||
|
|
||||||
$messages = array('', '');
|
$messages = array('', '');
|
||||||
$messages[] = $emptyLine = $formatter->format(sprintf('<error>%s</error>', str_repeat(' ', $len)));
|
$messages[] = $emptyLine = $formatter->format(sprintf('<error>%s</error>', str_repeat(' ', $len)));
|
||||||
$messages[] = $formatter->format(sprintf('<error>%s%s</error>', $title, str_repeat(' ', max(0, $len - $strlen($title)))));
|
$messages[] = $formatter->format(sprintf('<error>%s%s</error>', $title, str_repeat(' ', max(0, $len - $this->stringWidth($title)))));
|
||||||
foreach ($lines as $line) {
|
foreach ($lines as $line) {
|
||||||
$messages[] = $formatter->format(sprintf('<error> %s %s</error>', $line[0], str_repeat(' ', $len - $line[1])));
|
$messages[] = $formatter->format(sprintf('<error> %s %s</error>', $line[0], str_repeat(' ', $len - $line[1])));
|
||||||
}
|
}
|
||||||
@ -1114,4 +1104,53 @@ class Application
|
|||||||
{
|
{
|
||||||
$this->defaultCommand = $commandName;
|
$this->defaultCommand = $commandName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function stringWidth($string)
|
||||||
|
{
|
||||||
|
if (!function_exists('mb_strwidth')) {
|
||||||
|
return strlen($string);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === $encoding = mb_detect_encoding($string)) {
|
||||||
|
return strlen($string);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mb_strwidth($string, $encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function splitStringByWidth($string, $width)
|
||||||
|
{
|
||||||
|
// str_split is not suitable for multi-byte characters, we should use preg_split to get char array properly.
|
||||||
|
// additionally, array_slice() is not enough as some character has doubled width.
|
||||||
|
// we need a function to split string not by character count but by string width
|
||||||
|
|
||||||
|
if (!function_exists('mb_strwidth')) {
|
||||||
|
return str_split($string, $width);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === $encoding = mb_detect_encoding($string)) {
|
||||||
|
return str_split($string, $width);
|
||||||
|
}
|
||||||
|
|
||||||
|
$utf8String = mb_convert_encoding($string, 'utf8', $encoding);
|
||||||
|
$lines = array();
|
||||||
|
$line = '';
|
||||||
|
foreach (preg_split('//u', $utf8String) as $char) {
|
||||||
|
// test if $char could be appended to current line
|
||||||
|
if (mb_strwidth($line.$char) <= $width) {
|
||||||
|
$line .= $char;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// if not, push current line to array and make new line
|
||||||
|
$lines[] = str_pad($line, $width);
|
||||||
|
$line = $char;
|
||||||
|
}
|
||||||
|
if (strlen($line)) {
|
||||||
|
$lines[] = count($lines) ? str_pad($line, $width) : $line;
|
||||||
|
}
|
||||||
|
|
||||||
|
mb_convert_variables($encoding, 'utf8', $lines);
|
||||||
|
|
||||||
|
return $lines;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ abstract class Helper implements HelperInterface
|
|||||||
*/
|
*/
|
||||||
public static function strlen($string)
|
public static function strlen($string)
|
||||||
{
|
{
|
||||||
if (!function_exists('mb_strlen')) {
|
if (!function_exists('mb_strwidth')) {
|
||||||
return strlen($string);
|
return strlen($string);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ abstract class Helper implements HelperInterface
|
|||||||
return strlen($string);
|
return strlen($string);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mb_strlen($string, $encoding);
|
return mb_strwidth($string, $encoding);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function formatTime($secs)
|
public static function formatTime($secs)
|
||||||
|
@ -523,6 +523,33 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception4.txt', $tester->getDisplay(true), '->renderException() wraps messages when they are bigger than the terminal');
|
$this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception4.txt', $tester->getDisplay(true), '->renderException() wraps messages when they are bigger than the terminal');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testRenderExceptionWithDoubleWidthCharacters()
|
||||||
|
{
|
||||||
|
$application = $this->getMock('Symfony\Component\Console\Application', array('getTerminalWidth'));
|
||||||
|
$application->setAutoExit(false);
|
||||||
|
$application->expects($this->any())
|
||||||
|
->method('getTerminalWidth')
|
||||||
|
->will($this->returnValue(120));
|
||||||
|
$application->register('foo')->setCode(function () {throw new \Exception('エラーメッセージ');});
|
||||||
|
$tester = new ApplicationTester($application);
|
||||||
|
|
||||||
|
$tester->run(array('command' => 'foo'), array('decorated' => false));
|
||||||
|
$this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception_doublewidth1.txt', $tester->getDisplay(true), '->renderException() renderes a pretty exceptions with previous exceptions');
|
||||||
|
|
||||||
|
$tester->run(array('command' => 'foo'), array('decorated' => true));
|
||||||
|
$this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception_doublewidth1decorated.txt', $tester->getDisplay(true), '->renderException() renderes a pretty exceptions with previous exceptions');
|
||||||
|
|
||||||
|
$application = $this->getMock('Symfony\Component\Console\Application', array('getTerminalWidth'));
|
||||||
|
$application->setAutoExit(false);
|
||||||
|
$application->expects($this->any())
|
||||||
|
->method('getTerminalWidth')
|
||||||
|
->will($this->returnValue(32));
|
||||||
|
$application->register('foo')->setCode(function () {throw new \Exception('コマンドの実行中にエラーが発生しました。');});
|
||||||
|
$tester = new ApplicationTester($application);
|
||||||
|
$tester->run(array('command' => 'foo'), array('decorated' => false));
|
||||||
|
$this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception_doublewidth2.txt', $tester->getDisplay(true), '->renderException() wraps messages when they are bigger than the terminal');
|
||||||
|
}
|
||||||
|
|
||||||
public function testRun()
|
public function testRun()
|
||||||
{
|
{
|
||||||
$application = new Application();
|
$application = new Application();
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[Exception]
|
||||||
|
エラーメッセージ
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
foo
|
||||||
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
|
||||||
|
[37;41m [0m
|
||||||
|
[37;41m [Exception] [0m
|
||||||
|
[37;41m エラーメッセージ [0m
|
||||||
|
[37;41m [0m
|
||||||
|
|
||||||
|
|
||||||
|
[32mfoo[0m
|
||||||
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[Exception]
|
||||||
|
コマンドの実行中にエラーが
|
||||||
|
発生しました。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
foo
|
||||||
|
|
||||||
|
|
@ -54,7 +54,7 @@ class FormatterHelperTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
public function testFormatBlockWithDiacriticLetters()
|
public function testFormatBlockWithDiacriticLetters()
|
||||||
{
|
{
|
||||||
if (!extension_loaded('mbstring')) {
|
if (!function_exists('mb_detect_encoding')) {
|
||||||
$this->markTestSkipped('This test requires mbstring to work.');
|
$this->markTestSkipped('This test requires mbstring to work.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,6 +69,21 @@ class FormatterHelperTest extends \PHPUnit_Framework_TestCase
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testFormatBlockWithDoubleWidthDiacriticLetters()
|
||||||
|
{
|
||||||
|
if (!extension_loaded('mbstring')) {
|
||||||
|
$this->markTestSkipped('This test requires mbstring to work.');
|
||||||
|
}
|
||||||
|
$formatter = new FormatterHelper();
|
||||||
|
$this->assertEquals(
|
||||||
|
'<error> </error>'."\n" .
|
||||||
|
'<error> 表示するテキスト </error>'."\n" .
|
||||||
|
'<error> </error>',
|
||||||
|
$formatter->formatBlock('表示するテキスト', 'error', true),
|
||||||
|
'::formatBlock() formats a message in a block'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function testFormatBlockLGEscaping()
|
public function testFormatBlockLGEscaping()
|
||||||
{
|
{
|
||||||
$formatter = new FormatterHelper();
|
$formatter = new FormatterHelper();
|
||||||
|
@ -65,14 +65,18 @@ class TokenizerEscaping
|
|||||||
*/
|
*/
|
||||||
private function replaceUnicodeSequences($value)
|
private function replaceUnicodeSequences($value)
|
||||||
{
|
{
|
||||||
return preg_replace_callback($this->patterns->getUnicodeEscapePattern(), function (array $match) {
|
return preg_replace_callback($this->patterns->getUnicodeEscapePattern(), function ($match) {
|
||||||
$code = $match[1];
|
$c = hexdec($match[1]);
|
||||||
|
|
||||||
if (bin2hex($code) > 0xFFFD) {
|
if (0x80 > $c %= 0x200000) {
|
||||||
$code = '\\FFFD';
|
return chr($c);
|
||||||
|
}
|
||||||
|
if (0x800 > $c) {
|
||||||
|
return chr(0xC0 | $c>>6).chr(0x80 | $c & 0x3F);
|
||||||
|
}
|
||||||
|
if (0x10000 > $c) {
|
||||||
|
return chr(0xE0 | $c>>12).chr(0x80 | $c>>6 & 0x3F).chr(0x80 | $c & 0x3F);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mb_convert_encoding(pack('H*', $code), 'UTF-8', 'UCS-2BE');
|
|
||||||
}, $value);
|
}, $value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ interface ConfigurationExtensionInterface
|
|||||||
/**
|
/**
|
||||||
* Returns extension configuration
|
* Returns extension configuration
|
||||||
*
|
*
|
||||||
* @param array $config $config An array of configuration values
|
* @param array $config An array of configuration values
|
||||||
* @param ContainerBuilder $container A ContainerBuilder instance
|
* @param ContainerBuilder $container A ContainerBuilder instance
|
||||||
*
|
*
|
||||||
* @return ConfigurationInterface|null The configuration or null
|
* @return ConfigurationInterface|null The configuration or null
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" ?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<container xmlns="http://symfony.com/schema/dic/services"
|
<container xmlns="http://symfony.com/schema/dic/services"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
@ -94,7 +94,7 @@ class Finder implements \IteratorAggregate, \Countable
|
|||||||
*
|
*
|
||||||
* @return Finder The current Finder instance
|
* @return Finder The current Finder instance
|
||||||
*/
|
*/
|
||||||
public function addAdapter(Adapter\AdapterInterface $adapter, $priority = 0)
|
public function addAdapter(AdapterInterface $adapter, $priority = 0)
|
||||||
{
|
{
|
||||||
$this->adapters[$adapter->getName()] = array(
|
$this->adapters[$adapter->getName()] = array(
|
||||||
'adapter' => $adapter,
|
'adapter' => $adapter,
|
||||||
|
@ -195,25 +195,19 @@ class NumberToLocalizedStringTransformer implements DataTransformerInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (function_exists('mb_detect_encoding') && false !== $encoding = mb_detect_encoding($value)) {
|
if (function_exists('mb_detect_encoding') && false !== $encoding = mb_detect_encoding($value)) {
|
||||||
$strlen = function ($string) use ($encoding) {
|
$length = mb_strlen($value, $encoding);
|
||||||
return mb_strlen($string, $encoding);
|
$remainder = mb_substr($value, $position, $length, $encoding);
|
||||||
};
|
|
||||||
$substr = function ($string, $offset, $length) use ($encoding) {
|
|
||||||
return mb_substr($string, $offset, $length, $encoding);
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
$strlen = 'strlen';
|
$length = strlen($value);
|
||||||
$substr = 'substr';
|
$remainder = substr($value, $position, $length);
|
||||||
}
|
}
|
||||||
|
|
||||||
$length = $strlen($value);
|
|
||||||
|
|
||||||
// After parsing, position holds the index of the character where the
|
// After parsing, position holds the index of the character where the
|
||||||
// parsing stopped
|
// parsing stopped
|
||||||
if ($position < $length) {
|
if ($position < $length) {
|
||||||
// Check if there are unrecognized characters at the end of the
|
// Check if there are unrecognized characters at the end of the
|
||||||
// number (excluding whitespace characters)
|
// number (excluding whitespace characters)
|
||||||
$remainder = trim($substr($value, $position, $length), " \t\n\r\0\x0b\xc2\xa0");
|
$remainder = trim($remainder, " \t\n\r\0\x0b\xc2\xa0");
|
||||||
|
|
||||||
if ('' !== $remainder) {
|
if ('' !== $remainder) {
|
||||||
throw new TransformationFailedException(
|
throw new TransformationFailedException(
|
||||||
|
@ -215,7 +215,7 @@ class NumberToLocalizedStringTransformerTest extends \PHPUnit_Framework_TestCase
|
|||||||
// https://github.com/symfony/symfony/issues/7609
|
// https://github.com/symfony/symfony/issues/7609
|
||||||
public function testReverseTransformWithGroupingAndFixedSpaces()
|
public function testReverseTransformWithGroupingAndFixedSpaces()
|
||||||
{
|
{
|
||||||
if (!extension_loaded('mbstring')) {
|
if (!function_exists('mb_detect_encoding')) {
|
||||||
$this->markTestSkipped('The "mbstring" extension is required for this test.');
|
$this->markTestSkipped('The "mbstring" extension is required for this test.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -537,7 +537,7 @@ class NumberToLocalizedStringTransformerTest extends \PHPUnit_Framework_TestCase
|
|||||||
*/
|
*/
|
||||||
public function testReverseTransformDisallowsCenteredExtraCharactersMultibyte()
|
public function testReverseTransformDisallowsCenteredExtraCharactersMultibyte()
|
||||||
{
|
{
|
||||||
if (!extension_loaded('mbstring')) {
|
if (!function_exists('mb_detect_encoding')) {
|
||||||
$this->markTestSkipped('The "mbstring" extension is required for this test.');
|
$this->markTestSkipped('The "mbstring" extension is required for this test.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -554,7 +554,7 @@ class NumberToLocalizedStringTransformerTest extends \PHPUnit_Framework_TestCase
|
|||||||
*/
|
*/
|
||||||
public function testReverseTransformIgnoresTrailingSpacesInExceptionMessage()
|
public function testReverseTransformIgnoresTrailingSpacesInExceptionMessage()
|
||||||
{
|
{
|
||||||
if (!extension_loaded('mbstring')) {
|
if (!function_exists('mb_detect_encoding')) {
|
||||||
$this->markTestSkipped('The "mbstring" extension is required for this test.');
|
$this->markTestSkipped('The "mbstring" extension is required for this test.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -582,7 +582,7 @@ class NumberToLocalizedStringTransformerTest extends \PHPUnit_Framework_TestCase
|
|||||||
*/
|
*/
|
||||||
public function testReverseTransformDisallowsTrailingExtraCharactersMultibyte()
|
public function testReverseTransformDisallowsTrailingExtraCharactersMultibyte()
|
||||||
{
|
{
|
||||||
if (!extension_loaded('mbstring')) {
|
if (!function_exists('mb_detect_encoding')) {
|
||||||
$this->markTestSkipped('The "mbstring" extension is required for this test.');
|
$this->markTestSkipped('The "mbstring" extension is required for this test.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,32 +41,65 @@ class TrimListenerTest extends \PHPUnit_Framework_TestCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider codePointProvider
|
* @dataProvider spaceProvider
|
||||||
*/
|
*/
|
||||||
public function testTrimUtf8($chars)
|
public function testTrimUtf8Separators($hex)
|
||||||
{
|
{
|
||||||
if (!function_exists('mb_check_encoding')) {
|
if (!function_exists('mb_convert_encoding')) {
|
||||||
$this->markTestSkipped('The "mb_check_encoding" function is not available');
|
$this->markTestSkipped('The "mb_convert_encoding" function is not available');
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = mb_convert_encoding(pack('H*', implode('', $chars)), 'UTF-8', 'UCS-2BE');
|
// Convert hexadecimal representation into binary
|
||||||
$data = $data."ab\ncd".$data;
|
// H: hex string, high nibble first (UCS-2BE)
|
||||||
|
// *: repeat until end of string
|
||||||
|
$binary = pack('H*', $hex);
|
||||||
|
|
||||||
|
// Convert UCS-2BE to UTF-8
|
||||||
|
$symbol = mb_convert_encoding($binary, 'UTF-8', 'UCS-2BE');
|
||||||
|
$symbol = $symbol."ab\ncd".$symbol;
|
||||||
|
|
||||||
$form = $this->getMock('Symfony\Component\Form\Test\FormInterface');
|
$form = $this->getMock('Symfony\Component\Form\Test\FormInterface');
|
||||||
$event = new FormEvent($form, $data);
|
$event = new FormEvent($form, $symbol);
|
||||||
|
|
||||||
$filter = new TrimListener();
|
$filter = new TrimListener();
|
||||||
$filter->preSubmit($event);
|
$filter->preSubmit($event);
|
||||||
|
|
||||||
$this->assertSame("ab\ncd", $event->getData(), 'TrimListener should trim character(s): '.implode(', ', $chars));
|
$this->assertSame("ab\ncd", $event->getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function codePointProvider()
|
public function spaceProvider()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
'General category: Separator' => array(array('0020', '00A0', '1680', '180E', '2000', '2001', '2002', '2003', '2004', '2005', '2006', '2007', '2008', '2009', '200A', '2028', '2029', '202F', '205F', '3000')),
|
// separators
|
||||||
'General category: Other, control' => array(array('0009', '000A', '000B', '000C', '000D', '0085')),
|
array('0020'),
|
||||||
//'General category: Other, format. ZERO WIDTH SPACE' => array(array('200B')),
|
array('00A0'),
|
||||||
|
array('1680'),
|
||||||
|
// array('180E'),
|
||||||
|
array('2000'),
|
||||||
|
array('2001'),
|
||||||
|
array('2002'),
|
||||||
|
array('2003'),
|
||||||
|
array('2004'),
|
||||||
|
array('2005'),
|
||||||
|
array('2006'),
|
||||||
|
array('2007'),
|
||||||
|
array('2008'),
|
||||||
|
array('2009'),
|
||||||
|
array('200A'),
|
||||||
|
array('2028'),
|
||||||
|
array('2029'),
|
||||||
|
array('202F'),
|
||||||
|
array('205F'),
|
||||||
|
array('3000'),
|
||||||
|
// controls
|
||||||
|
array('0009'),
|
||||||
|
array('000A'),
|
||||||
|
array('000B'),
|
||||||
|
array('000C'),
|
||||||
|
array('000D'),
|
||||||
|
array('0085'),
|
||||||
|
// zero width space
|
||||||
|
// array('200B'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ class AclVoterTest extends \PHPUnit_Framework_TestCase
|
|||||||
*/
|
*/
|
||||||
public function testSupportsAttribute($attribute, $supported)
|
public function testSupportsAttribute($attribute, $supported)
|
||||||
{
|
{
|
||||||
list($voter,, $permissionMap,,) = $this->getVoter();
|
list($voter,, $permissionMap,,) = $this->getVoter(true, false);
|
||||||
|
|
||||||
$permissionMap
|
$permissionMap
|
||||||
->expects($this->once())
|
->expects($this->once())
|
||||||
@ -39,6 +39,16 @@ class AclVoterTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertSame($supported, $voter->supportsAttribute($attribute));
|
$this->assertSame($supported, $voter->supportsAttribute($attribute));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider getSupportsAttributeNonStringTests
|
||||||
|
*/
|
||||||
|
public function testSupportsAttributeNonString($attribute)
|
||||||
|
{
|
||||||
|
list($voter,,,,,) = $this->getVoter(true, false);
|
||||||
|
|
||||||
|
$this->assertFalse($voter->supportsAttribute($attribute));
|
||||||
|
}
|
||||||
|
|
||||||
public function getSupportsAttributeTests()
|
public function getSupportsAttributeTests()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
@ -47,6 +57,16 @@ class AclVoterTest extends \PHPUnit_Framework_TestCase
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getSupportsAttributeNonStringTests()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array(new \stdClass()),
|
||||||
|
array(1),
|
||||||
|
array(true),
|
||||||
|
array(array()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider getSupportsClassTests
|
* @dataProvider getSupportsClassTests
|
||||||
*/
|
*/
|
||||||
@ -387,13 +407,20 @@ class AclVoterTest extends \PHPUnit_Framework_TestCase
|
|||||||
return $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
|
return $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getVoter($allowIfObjectIdentityUnavailable = true)
|
protected function getVoter($allowIfObjectIdentityUnavailable = true, $alwaysContains = true)
|
||||||
{
|
{
|
||||||
$provider = $this->getMock('Symfony\Component\Security\Acl\Model\AclProviderInterface');
|
$provider = $this->getMock('Symfony\Component\Security\Acl\Model\AclProviderInterface');
|
||||||
$permissionMap = $this->getMock('Symfony\Component\Security\Acl\Permission\PermissionMapInterface');
|
$permissionMap = $this->getMock('Symfony\Component\Security\Acl\Permission\PermissionMapInterface');
|
||||||
$oidStrategy = $this->getMock('Symfony\Component\Security\Acl\Model\ObjectIdentityRetrievalStrategyInterface');
|
$oidStrategy = $this->getMock('Symfony\Component\Security\Acl\Model\ObjectIdentityRetrievalStrategyInterface');
|
||||||
$sidStrategy = $this->getMock('Symfony\Component\Security\Acl\Model\SecurityIdentityRetrievalStrategyInterface');
|
$sidStrategy = $this->getMock('Symfony\Component\Security\Acl\Model\SecurityIdentityRetrievalStrategyInterface');
|
||||||
|
|
||||||
|
if ($alwaysContains) {
|
||||||
|
$permissionMap
|
||||||
|
->expects($this->any())
|
||||||
|
->method('contains')
|
||||||
|
->will($this->returnValue(true));
|
||||||
|
}
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
new AclVoter($provider, $oidStrategy, $sidStrategy, $permissionMap, null, $allowIfObjectIdentityUnavailable),
|
new AclVoter($provider, $oidStrategy, $sidStrategy, $permissionMap, null, $allowIfObjectIdentityUnavailable),
|
||||||
$provider,
|
$provider,
|
||||||
|
@ -48,12 +48,16 @@ class AclVoter implements VoterInterface
|
|||||||
|
|
||||||
public function supportsAttribute($attribute)
|
public function supportsAttribute($attribute)
|
||||||
{
|
{
|
||||||
return $this->permissionMap->contains($attribute);
|
return is_string($attribute) && $this->permissionMap->contains($attribute);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function vote(TokenInterface $token, $object, array $attributes)
|
public function vote(TokenInterface $token, $object, array $attributes)
|
||||||
{
|
{
|
||||||
foreach ($attributes as $attribute) {
|
foreach ($attributes as $attribute) {
|
||||||
|
if (!$this->supportsAttribute($attribute)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (null === $masks = $this->permissionMap->getMasks($attribute, $object)) {
|
if (null === $masks = $this->permissionMap->getMasks($attribute, $object)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -12,19 +12,7 @@
|
|||||||
namespace Symfony\Component\Security\Csrf\TokenGenerator;
|
namespace Symfony\Component\Security\Csrf\TokenGenerator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates and validates CSRF tokens.
|
* Generates CSRF tokens.
|
||||||
*
|
|
||||||
* You can generate a CSRF token by using the method {@link generateCsrfToken()}.
|
|
||||||
* This method expects a unique token ID as argument. The token ID can later be
|
|
||||||
* used to validate a token provided by the user.
|
|
||||||
*
|
|
||||||
* Token IDs do not necessarily have to be secret, but they should NEVER be
|
|
||||||
* created from data provided by the client. A good practice is to hard-code the
|
|
||||||
* token IDs for the various CSRF tokens used by your application.
|
|
||||||
*
|
|
||||||
* You should use the method {@link isCsrfTokenValid()} to check a CSRF token
|
|
||||||
* submitted by the client. This method will return true if the CSRF token is
|
|
||||||
* valid.
|
|
||||||
*
|
*
|
||||||
* @since 2.4
|
* @since 2.4
|
||||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
@ -157,7 +157,7 @@ class PoFileLoader extends ArrayLoader implements LoaderInterface
|
|||||||
private function addMessage(array &$messages, array $item)
|
private function addMessage(array &$messages, array $item)
|
||||||
{
|
{
|
||||||
if (is_array($item['translated'])) {
|
if (is_array($item['translated'])) {
|
||||||
$messages[$item['ids']['singular']] = stripslashes($item['translated'][0]);
|
$messages[$item['ids']['singular']] = stripcslashes($item['translated'][0]);
|
||||||
if (isset($item['ids']['plural'])) {
|
if (isset($item['ids']['plural'])) {
|
||||||
$plurals = $item['translated'];
|
$plurals = $item['translated'];
|
||||||
// PO are by definition indexed so sort by index.
|
// PO are by definition indexed so sort by index.
|
||||||
@ -172,7 +172,7 @@ class PoFileLoader extends ArrayLoader implements LoaderInterface
|
|||||||
$messages[$item['ids']['plural']] = stripcslashes(implode('|', $plurals));
|
$messages[$item['ids']['plural']] = stripcslashes(implode('|', $plurals));
|
||||||
}
|
}
|
||||||
} elseif (!empty($item['ids']['singular'])) {
|
} elseif (!empty($item['ids']['singular'])) {
|
||||||
$messages[$item['ids']['singular']] = stripslashes($item['translated']);
|
$messages[$item['ids']['singular']] = stripcslashes($item['translated']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ class IcuResFileDumperTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
public function testDump()
|
public function testDump()
|
||||||
{
|
{
|
||||||
if (!extension_loaded('mbstring')) {
|
if (!function_exists('mb_convert_encoding')) {
|
||||||
$this->markTestSkipped('This test requires mbstring to work.');
|
$this->markTestSkipped('This test requires mbstring to work.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,10 +79,16 @@ class StaticMethodLoaderTest extends \PHPUnit_Framework_TestCase
|
|||||||
public function testLoadClassMetadataIgnoresAbstractMethods()
|
public function testLoadClassMetadataIgnoresAbstractMethods()
|
||||||
{
|
{
|
||||||
$loader = new StaticMethodLoader('loadMetadata');
|
$loader = new StaticMethodLoader('loadMetadata');
|
||||||
|
$caught = false;
|
||||||
try {
|
try {
|
||||||
include __DIR__ . '/AbstractMethodStaticLoader.php';
|
include __DIR__.'/AbstractMethodStaticLoader.php';
|
||||||
$this->fail('AbstractMethodStaticLoader should produce a strict standard error.');
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
|
// catching the PHP notice that is converted to an exception by PHPUnit
|
||||||
|
$caught = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$caught) {
|
||||||
|
$this->fail('AbstractMethodStaticLoader should produce a strict standard error.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$metadata = new ClassMetadata(__NAMESPACE__.'\AbstractMethodStaticLoader');
|
$metadata = new ClassMetadata(__NAMESPACE__.'\AbstractMethodStaticLoader');
|
||||||
|
@ -55,7 +55,7 @@ class Parser
|
|||||||
$this->currentLine = '';
|
$this->currentLine = '';
|
||||||
$this->lines = explode("\n", $this->cleanup($value));
|
$this->lines = explode("\n", $this->cleanup($value));
|
||||||
|
|
||||||
if (function_exists('mb_detect_encoding') && false === mb_detect_encoding($value, 'UTF-8', true)) {
|
if (!preg_match('//u', $value)) {
|
||||||
throw new ParseException('The YAML value does not appear to be valid UTF-8.');
|
throw new ParseException('The YAML value does not appear to be valid UTF-8.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,12 +33,6 @@ class ParserTest extends \PHPUnit_Framework_TestCase
|
|||||||
*/
|
*/
|
||||||
public function testSpecifications($file, $expected, $yaml, $comment)
|
public function testSpecifications($file, $expected, $yaml, $comment)
|
||||||
{
|
{
|
||||||
if ('escapedCharacters' == $file) {
|
|
||||||
if (!function_exists('iconv') && !function_exists('mb_convert_encoding')) {
|
|
||||||
$this->markTestSkipped('The iconv and mbstring extensions are not available.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->assertEquals($expected, var_export($this->parser->parse($yaml), true), $comment);
|
$this->assertEquals($expected, var_export($this->parser->parse($yaml), true), $comment);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,8 +440,8 @@ EOF;
|
|||||||
|
|
||||||
public function testNonUtf8Exception()
|
public function testNonUtf8Exception()
|
||||||
{
|
{
|
||||||
if (!function_exists('mb_detect_encoding') || !function_exists('iconv')) {
|
if (!function_exists('iconv')) {
|
||||||
$this->markTestSkipped('Exceptions for non-utf8 charsets require the mb_detect_encoding() and iconv() functions.');
|
$this->markTestSkipped('Exceptions for non-utf8 charsets require the iconv() function.');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ class Unescaper
|
|||||||
{
|
{
|
||||||
// Parser and Inline assume UTF-8 encoding, so escaped Unicode characters
|
// Parser and Inline assume UTF-8 encoding, so escaped Unicode characters
|
||||||
// must be converted to that encoding.
|
// must be converted to that encoding.
|
||||||
|
// @deprecated since 2.5, to be removed in 3.0
|
||||||
const ENCODING = 'UTF-8';
|
const ENCODING = 'UTF-8';
|
||||||
|
|
||||||
// Regex fragment that matches an escaped character in a double quoted
|
// Regex fragment that matches an escaped character in a double quoted
|
||||||
@ -80,13 +81,13 @@ class Unescaper
|
|||||||
case 'n':
|
case 'n':
|
||||||
return "\n";
|
return "\n";
|
||||||
case 'v':
|
case 'v':
|
||||||
return "\xb";
|
return "\xB";
|
||||||
case 'f':
|
case 'f':
|
||||||
return "\xc";
|
return "\xC";
|
||||||
case 'r':
|
case 'r':
|
||||||
return "\xd";
|
return "\r";
|
||||||
case 'e':
|
case 'e':
|
||||||
return "\x1b";
|
return "\x1B";
|
||||||
case ' ':
|
case ' ':
|
||||||
return ' ';
|
return ' ';
|
||||||
case '"':
|
case '"':
|
||||||
@ -97,50 +98,44 @@ class Unescaper
|
|||||||
return '\\';
|
return '\\';
|
||||||
case 'N':
|
case 'N':
|
||||||
// U+0085 NEXT LINE
|
// U+0085 NEXT LINE
|
||||||
return $this->convertEncoding("\x00\x85", self::ENCODING, 'UCS-2BE');
|
return "\xC2\x85";
|
||||||
case '_':
|
case '_':
|
||||||
// U+00A0 NO-BREAK SPACE
|
// U+00A0 NO-BREAK SPACE
|
||||||
return $this->convertEncoding("\x00\xA0", self::ENCODING, 'UCS-2BE');
|
return "\xC2\xA0";
|
||||||
case 'L':
|
case 'L':
|
||||||
// U+2028 LINE SEPARATOR
|
// U+2028 LINE SEPARATOR
|
||||||
return $this->convertEncoding("\x20\x28", self::ENCODING, 'UCS-2BE');
|
return "\xE2\x80\xA8";
|
||||||
case 'P':
|
case 'P':
|
||||||
// U+2029 PARAGRAPH SEPARATOR
|
// U+2029 PARAGRAPH SEPARATOR
|
||||||
return $this->convertEncoding("\x20\x29", self::ENCODING, 'UCS-2BE');
|
return "\xE2\x80\xA9";
|
||||||
case 'x':
|
case 'x':
|
||||||
$char = pack('n', hexdec(substr($value, 2, 2)));
|
return self::utf8chr(hexdec(substr($value, 2, 2)));
|
||||||
|
|
||||||
return $this->convertEncoding($char, self::ENCODING, 'UCS-2BE');
|
|
||||||
case 'u':
|
case 'u':
|
||||||
$char = pack('n', hexdec(substr($value, 2, 4)));
|
return self::utf8chr(hexdec(substr($value, 2, 4)));
|
||||||
|
|
||||||
return $this->convertEncoding($char, self::ENCODING, 'UCS-2BE');
|
|
||||||
case 'U':
|
case 'U':
|
||||||
$char = pack('N', hexdec(substr($value, 2, 8)));
|
return self::utf8chr(hexdec(substr($value, 2, 8)));
|
||||||
|
|
||||||
return $this->convertEncoding($char, self::ENCODING, 'UCS-4BE');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a string from one encoding to another.
|
* Get the UTF-8 character for the given code point.
|
||||||
*
|
*
|
||||||
* @param string $value The string to convert
|
* @param int $c The unicode code point
|
||||||
* @param string $to The input encoding
|
|
||||||
* @param string $from The output encoding
|
|
||||||
*
|
*
|
||||||
* @return string The string with the new encoding
|
* @return string The corresponding UTF-8 character
|
||||||
*
|
|
||||||
* @throws \RuntimeException if no suitable encoding function is found (iconv or mbstring)
|
|
||||||
*/
|
*/
|
||||||
private function convertEncoding($value, $to, $from)
|
private static function utf8chr($c)
|
||||||
{
|
{
|
||||||
if (function_exists('mb_convert_encoding')) {
|
if (0x80 > $c %= 0x200000) {
|
||||||
return mb_convert_encoding($value, $to, $from);
|
return chr($c);
|
||||||
} elseif (function_exists('iconv')) {
|
}
|
||||||
return iconv($from, $to, $value);
|
if (0x800 > $c) {
|
||||||
|
return chr(0xC0 | $c>>6).chr(0x80 | $c & 0x3F);
|
||||||
|
}
|
||||||
|
if (0x10000 > $c) {
|
||||||
|
return chr(0xE0 | $c>>12).chr(0x80 | $c>>6 & 0x3F).chr(0x80 | $c & 0x3F);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new \RuntimeException('No suitable convert encoding function (install the iconv or mbstring extension).');
|
return chr(0xF0 | $c>>18).chr(0x80 | $c>>12 & 0x3F).chr(0x80 | $c>>6 & 0x3F).chr(0x80 | $c & 0x3F);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user