diff --git a/.travis.yml b/.travis.yml index 7ce8aebbf0..53c2de19a1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,7 +20,6 @@ matrix: - php: hhvm allow_failures: - php: nightly - - php: hhvm fast_finish: true services: mongodb diff --git a/src/Symfony/Bridge/Doctrine/Logger/DbalLogger.php b/src/Symfony/Bridge/Doctrine/Logger/DbalLogger.php index 617dd5c3fa..2d834d7d40 100644 --- a/src/Symfony/Bridge/Doctrine/Logger/DbalLogger.php +++ b/src/Symfony/Bridge/Doctrine/Logger/DbalLogger.php @@ -50,30 +50,7 @@ class DbalLogger implements SQLLogger } if (is_array($params)) { - foreach ($params as $index => $param) { - if (!is_string($params[$index])) { - continue; - } - - // non utf-8 strings break json encoding - if (!preg_match('//u', $params[$index])) { - $params[$index] = self::BINARY_DATA_VALUE; - continue; - } - - // detect if the too long string must be shorten - if (function_exists('mb_strlen')) { - if (self::MAX_STRING_LENGTH < mb_strlen($params[$index], 'UTF-8')) { - $params[$index] = mb_substr($params[$index], 0, self::MAX_STRING_LENGTH - 6, 'UTF-8').' [...]'; - continue; - } - } else { - if (self::MAX_STRING_LENGTH < strlen($params[$index])) { - $params[$index] = substr($params[$index], 0, self::MAX_STRING_LENGTH - 6).' [...]'; - continue; - } - } - } + $params = $this->normalizeParams($params); } if (null !== $this->logger) { @@ -101,4 +78,40 @@ class DbalLogger implements SQLLogger { $this->logger->debug($message, $params); } + + private function normalizeParams(array $params) + { + foreach ($params as $index => $param) { + // normalize recursively + if (is_array($param)) { + $params[$index] = $this->normalizeParams($param); + continue; + } + + if (!is_string($params[$index])) { + continue; + } + + // non utf-8 strings break json encoding + if (!preg_match('//u', $params[$index])) { + $params[$index] = self::BINARY_DATA_VALUE; + continue; + } + + // detect if the too long string must be shorten + if (function_exists('mb_strlen')) { + if (self::MAX_STRING_LENGTH < mb_strlen($params[$index], 'UTF-8')) { + $params[$index] = mb_substr($params[$index], 0, self::MAX_STRING_LENGTH - 6, 'UTF-8').' [...]'; + continue; + } + } else { + if (self::MAX_STRING_LENGTH < strlen($params[$index])) { + $params[$index] = substr($params[$index], 0, self::MAX_STRING_LENGTH - 6).' [...]'; + continue; + } + } + } + + return $params; + } } diff --git a/src/Symfony/Bridge/Doctrine/Tests/Logger/DbalLoggerTest.php b/src/Symfony/Bridge/Doctrine/Tests/Logger/DbalLoggerTest.php index fe7f0a30ac..417a3fd02e 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Logger/DbalLoggerTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Logger/DbalLoggerTest.php @@ -73,6 +73,37 @@ class DbalLoggerTest extends \PHPUnit_Framework_TestCase )); } + public function testLogNonUtf8Array() + { + $logger = $this->getMock('Psr\\Log\\LoggerInterface'); + + $dbalLogger = $this + ->getMockBuilder('Symfony\\Bridge\\Doctrine\\Logger\\DbalLogger') + ->setConstructorArgs(array($logger, null)) + ->setMethods(array('log')) + ->getMock() + ; + + $dbalLogger + ->expects($this->once()) + ->method('log') + ->with('SQL', array( + 'utf8' => 'foo', + array( + 'nonutf8' => DbalLogger::BINARY_DATA_VALUE, + ) + ) + ) + ; + + $dbalLogger->startQuery('SQL', array( + 'utf8' => 'foo', + array( + 'nonutf8' => "\x7F\xFF", + ) + )); + } + public function testLogLongString() { $logger = $this->getMock('Psr\\Log\\LoggerInterface'); diff --git a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php index 218422fea4..0fbf42c5be 100644 --- a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php +++ b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php @@ -82,7 +82,7 @@ class UniqueEntityValidator extends ConstraintValidator $criteria = array(); foreach ($fields as $fieldName) { if (!$class->hasField($fieldName) && !$class->hasAssociation($fieldName)) { - throw new ConstraintDefinitionException(sprintf("The field '%s' is not mapped by Doctrine, so it cannot be validated for uniqueness.", $fieldName)); + throw new ConstraintDefinitionException(sprintf('The field "%s" is not mapped by Doctrine, so it cannot be validated for uniqueness.', $fieldName)); } $criteria[$fieldName] = $class->reflFields[$fieldName]->getValue($entity); diff --git a/src/Symfony/Bridge/Monolog/Processor/WebProcessor.php b/src/Symfony/Bridge/Monolog/Processor/WebProcessor.php index dbe01a4e48..2752d03a58 100644 --- a/src/Symfony/Bridge/Monolog/Processor/WebProcessor.php +++ b/src/Symfony/Bridge/Monolog/Processor/WebProcessor.php @@ -21,10 +21,10 @@ use Symfony\Component\HttpKernel\Event\GetResponseEvent; */ class WebProcessor extends BaseWebProcessor { - public function __construct() + public function __construct(array $extraFields = null) { // Pass an empty array as the default null value would access $_SERVER - parent::__construct(array()); + parent::__construct(array(), $extraFields); } public function onKernelRequest(GetResponseEvent $event) diff --git a/src/Symfony/Bridge/Monolog/Tests/Processor/WebProcessorTest.php b/src/Symfony/Bridge/Monolog/Tests/Processor/WebProcessorTest.php index 1022f78c1f..1232bfacf1 100644 --- a/src/Symfony/Bridge/Monolog/Tests/Processor/WebProcessorTest.php +++ b/src/Symfony/Bridge/Monolog/Tests/Processor/WebProcessorTest.php @@ -18,6 +18,42 @@ use Symfony\Component\HttpFoundation\Request; class WebProcessorTest extends \PHPUnit_Framework_TestCase { public function testUsesRequestServerData() + { + list($event, $server) = $this->createRequestEvent(); + + $processor = new WebProcessor(); + $processor->onKernelRequest($event); + $record = $processor($this->getRecord()); + + $this->assertCount(5, $record['extra']); + $this->assertEquals($server['REQUEST_URI'], $record['extra']['url']); + $this->assertEquals($server['REMOTE_ADDR'], $record['extra']['ip']); + $this->assertEquals($server['REQUEST_METHOD'], $record['extra']['http_method']); + $this->assertEquals($server['SERVER_NAME'], $record['extra']['server']); + $this->assertEquals($server['HTTP_REFERER'], $record['extra']['referrer']); + } + + public function testCanBeConstructedWithExtraFields() + { + if (!$this->isExtraFieldsSupported()) { + $this->markTestSkipped('WebProcessor of the installed Monolog version does not support $extraFields parameter'); + } + + list($event, $server) = $this->createRequestEvent(); + + $processor = new WebProcessor(array('url', 'referrer')); + $processor->onKernelRequest($event); + $record = $processor($this->getRecord()); + + $this->assertCount(2, $record['extra']); + $this->assertEquals($server['REQUEST_URI'], $record['extra']['url']); + $this->assertEquals($server['HTTP_REFERER'], $record['extra']['referrer']); + } + + /** + * @return array + */ + private function createRequestEvent() { $server = array( 'REQUEST_URI' => 'A', @@ -40,15 +76,7 @@ class WebProcessorTest extends \PHPUnit_Framework_TestCase ->method('getRequest') ->will($this->returnValue($request)); - $processor = new WebProcessor(); - $processor->onKernelRequest($event); - $record = $processor($this->getRecord()); - - $this->assertEquals($server['REQUEST_URI'], $record['extra']['url']); - $this->assertEquals($server['REMOTE_ADDR'], $record['extra']['ip']); - $this->assertEquals($server['REQUEST_METHOD'], $record['extra']['http_method']); - $this->assertEquals($server['SERVER_NAME'], $record['extra']['server']); - $this->assertEquals($server['HTTP_REFERER'], $record['extra']['referrer']); + return array($event, $server); } /** @@ -57,7 +85,7 @@ class WebProcessorTest extends \PHPUnit_Framework_TestCase * * @return array Record */ - protected function getRecord($level = Logger::WARNING, $message = 'test') + private function getRecord($level = Logger::WARNING, $message = 'test') { return array( 'message' => $message, @@ -69,4 +97,17 @@ class WebProcessorTest extends \PHPUnit_Framework_TestCase 'extra' => array(), ); } + + private function isExtraFieldsSupported() + { + $monologWebProcessorClass = new \ReflectionClass('Monolog\Processor\WebProcessor'); + + foreach ($monologWebProcessorClass->getConstructor()->getParameters() as $parameter) { + if ('extraFields' === $parameter->getName()) { + return true; + } + } + + return false; + } } diff --git a/src/Symfony/Bridge/PhpUnit/README.md b/src/Symfony/Bridge/PhpUnit/README.md index 734df8baa0..afc9d8dd3b 100644 --- a/src/Symfony/Bridge/PhpUnit/README.md +++ b/src/Symfony/Bridge/PhpUnit/README.md @@ -6,6 +6,7 @@ Provides utilities for PHPUnit, especially user deprecation notices management. It comes with the following features: * disable the garbage collector; + * enforce a consistent `C` locale; * auto-register `class_exists` to load Doctrine annotations; * print a user deprecation notices summary at the end of the test suite. diff --git a/src/Symfony/Bridge/PhpUnit/bootstrap.php b/src/Symfony/Bridge/PhpUnit/bootstrap.php index b979ca818b..75a4b68ad3 100644 --- a/src/Symfony/Bridge/PhpUnit/bootstrap.php +++ b/src/Symfony/Bridge/PhpUnit/bootstrap.php @@ -12,6 +12,9 @@ if (!defined('PHPUNIT_COMPOSER_INSTALL') && !class_exists('PHPUnit_TextUI_Comman // https://bugs.php.net/bug.php?id=53976 gc_disable(); +// Enforce a consistent locale +setlocale(LC_ALL, 'C'); + if (class_exists('Doctrine\Common\Annotations\AnnotationRegistry')) { AnnotationRegistry::registerLoader('class_exists'); } diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php index b7c6876231..8cca8eec09 100644 --- a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php +++ b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php @@ -68,9 +68,9 @@ class ProxyDumper implements DumperInterface { $instantiation = 'return'; - if (ContainerInterface::SCOPE_CONTAINER === $definition->getScope()) { + if ($definition->isShared() && ContainerInterface::SCOPE_CONTAINER === $definition->getScope(false)) { $instantiation .= " \$this->services['$id'] ="; - } elseif (ContainerInterface::SCOPE_PROTOTYPE !== $scope = $definition->getScope()) { + } elseif ($definition->isShared() && ContainerInterface::SCOPE_PROTOTYPE !== $scope = $definition->getScope(false)) { $instantiation .= " \$this->services['$id'] = \$this->scopedServices['$scope']['$id'] ="; } diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig index c1f4d1e700..7405612a9b 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig @@ -98,6 +98,7 @@ {%- for child in form %} {{- form_widget(child, { parent_label_class: label_attr.class|default(''), + translation_domain: choice_translation_domain, }) -}} {% endfor -%} @@ -106,6 +107,7 @@ {%- for child in form %} {{- form_widget(child, { parent_label_class: label_attr.class|default(''), + translation_domain: choice_translation_domain, }) -}} {% endfor -%} @@ -156,7 +158,7 @@ {%- endblock radio_label %} {% block checkbox_radio_label %} - {# Do no display the label if widget is not defined in order to prevent double label rendering #} + {# Do not display the label if widget is not defined in order to prevent double label rendering #} {% if widget is defined %} {% if required %} {% set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' required')|trim}) %} @@ -169,7 +171,7 @@ {% endif %} {{- widget|raw -}} - {{- label is not sameas(false) ? label|trans({}, translation_domain) -}} + {{- label is not sameas(false) ? (translation_domain is sameas(false) ? label : label|trans({}, translation_domain)) -}} {% endif %} {% endblock checkbox_radio_label %} diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig index 13603812c0..aecc9fb194 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig @@ -46,7 +46,7 @@
{%- for child in form %} {{- form_widget(child) -}} - {{- form_label(child) -}} + {{- form_label(child, null, {translation_domain: choice_translation_domain}) -}} {% endfor -%}
{%- endblock choice_widget_expanded -%} @@ -57,7 +57,7 @@ {%- endif -%}