Merge branch '4.2'

* 4.2: (27 commits)
  cs fix
  cs fix
  [PHPUnit-Bridge] override some environment variables
  [TwigBridge] Remove use spaceless tag
  Upgrade zookeeper ext
  [translation] Update defaut format from yml to yaml
  Change default log level for output streams
  update docblock to match the actual behavior
  Don't resolve the Deprecation error handler mode until a deprecation is triggered
  compatibility with phpunit8
  Make 'headers' key optional for encoded messages
  [Debug][DebugClassLoader] Detect annotations before blank docblock lines on final and internal methods
  Fix undefined variable fromConstructor when passing context to getTypes
  Added translations for chineese language.
  Allow 3rd argument to be null
  Remove whitespace (tab on blank line)
  [Monolog] Really reset logger when calling logger::reset()
  [Form] Fixes debug:form appears many times as type extensions configured with new getExtendedTypes method
  Update src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php
  Update src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php
  ...
This commit is contained in:
Nicolas Grekas 2019-03-10 11:14:34 +01:00
commit bed7694132
24 changed files with 298 additions and 46 deletions

View File

@ -159,7 +159,7 @@ before_install:
tfold ext.apcu tpecl apcu-5.1.16 apcu.so $INI
tfold ext.mongodb tpecl mongodb-1.6.0alpha1 mongodb.so $INI
tfold ext.igbinary tpecl igbinary-2.0.8 igbinary.so $INI
tfold ext.zookeeper tpecl zookeeper-0.6.0 zookeeper.so $INI
tfold ext.zookeeper tpecl zookeeper-0.7.1 zookeeper.so $INI
tfold ext.amqp tpecl amqp-1.9.4 amqp.so $INI
done

View File

@ -12,6 +12,7 @@
namespace Symfony\Bridge\Monolog;
use Monolog\Logger as BaseLogger;
use Monolog\ResettableInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
use Symfony\Contracts\Service\ResetInterface;
@ -73,6 +74,10 @@ class Logger extends BaseLogger implements DebugLoggerInterface, ResetInterface
public function reset()
{
$this->clear();
if ($this instanceof ResettableInterface) {
parent::reset();
}
}
/**

View File

@ -12,6 +12,7 @@
namespace Symfony\Bridge\Monolog\Tests;
use Monolog\Handler\TestHandler;
use Monolog\ResettableInterface;
use PHPUnit\Framework\TestCase;
use Symfony\Bridge\Monolog\Logger;
use Symfony\Bridge\Monolog\Processor\DebugProcessor;
@ -108,6 +109,22 @@ class LoggerTest extends TestCase
$this->assertSame(0, $logger->countErrors());
}
public function testReset()
{
$handler = new TestHandler();
$logger = new Logger('test', [$handler]);
$logger->pushProcessor(new DebugProcessor());
$logger->info('test');
$logger->reset();
$this->assertEmpty($logger->getLogs());
$this->assertSame(0, $logger->countErrors());
if (class_exists(ResettableInterface::class)) {
$this->assertEmpty($handler->getRecords());
}
}
/**
* @group legacy
* @expectedDeprecation The "Symfony\Bridge\Monolog\Logger::getLogs()" method will have a new "Request $request = null" argument in version 5.0, not defining it is deprecated since Symfony 4.2.

View File

@ -58,10 +58,7 @@ if (PHP_VERSION_ID >= 70100) {
$PHPUNIT_VERSION = '4.8';
}
if ('composer.json' !== $COMPOSER_JSON = getenv('COMPOSER') ?: 'composer.json') {
putenv('COMPOSER=composer.json');
$_SERVER['COMPOSER'] = $_ENV['COMPOSER'] = 'composer.json';
}
$COMPOSER_JSON = getenv('COMPOSER') ?: 'composer.json';
$root = __DIR__;
while (!file_exists($root.'/'.$COMPOSER_JSON) || file_exists($root.'/DeprecationErrorHandler.php')) {
@ -79,6 +76,19 @@ if ('phpdbg' === PHP_SAPI) {
$PHP .= ' -qrr';
}
$defaultEnvs = [
'COMPOSER' => 'composer.json',
'COMPOSER_VENDOR_DIR' => 'vendor',
'COMPOSER_BIN_DIR' => 'bin',
];
foreach ($defaultEnvs as $envName => $envValue) {
if ($envValue !== getenv($envName)) {
putenv("$envName=$envValue");
$_SERVER[$envName] = $_ENV[$envName] = $envValue;
}
}
$COMPOSER = file_exists($COMPOSER = $oldPwd.'/composer.phar') || ($COMPOSER = rtrim('\\' === DIRECTORY_SEPARATOR ? preg_replace('/[\r\n].*/', '', `where.exe composer.phar`) : `which composer.phar 2> /dev/null`))
? $PHP.' '.escapeshellarg($COMPOSER)
: 'composer';

View File

@ -1,25 +1,19 @@
{% block _text_id_widget %}
{% spaceless %}
{% block _text_id_widget -%}
<div id="container">
{{ form_widget(form) }}
{{- form_widget(form) -}}
</div>
{% endspaceless %}
{% endblock _text_id_widget %}
{%- endblock _text_id_widget %}
{% block _names_entry_label %}
{% spaceless %}
{% block _names_entry_label -%}
{% if label is empty %}
{% set label = name|humanize %}
{% endif %}
{%- set label = name|humanize -%}
{% endif -%}
<label>Custom label: {{ label|trans(label_translation_parameters, translation_domain) }}</label>
{% endspaceless %}
{% endblock _names_entry_label %}
{%- endblock _names_entry_label %}
{% block _name_c_entry_label %}
{% spaceless %}
{% block _name_c_entry_label -%}
{% if label is empty %}
{% set label = name|humanize %}
{% endif %}
{%- set label = name|humanize -%}
{% endif -%}
<label>Custom name label: {{ label|trans(label_translation_parameters, translation_domain) }}</label>
{% endspaceless %}
{% endblock _name_c_entry_label %}
{%- endblock _name_c_entry_label %}

View File

@ -1,6 +1,4 @@
{% block form_widget_simple %}
{% spaceless %}
{% set type = type|default('text') %}
{%- set type = type|default('text') -%}
<input type="{{ type }}" {{ block('widget_attributes') }} value="{{ value }}" rel="theme" />
{% endspaceless %}
{% endblock form_widget_simple %}
{%- endblock form_widget_simple %}

View File

@ -1,8 +1,6 @@
{% extends 'form_div_layout.html.twig' %}
{% block form_widget_simple %}
{% spaceless %}
{% set type = type|default('text') %}
{%- set type = type|default('text') -%}
<input type="{{ type }}" {{ block('widget_attributes') }} value="{{ value }}" rel="theme" />
{% endspaceless %}
{% endblock form_widget_simple %}
{%- endblock form_widget_simple %}

View File

@ -1,8 +1,6 @@
{% use 'form_div_layout.html.twig' %}
{% block form_widget_simple %}
{% spaceless %}
{% set type = type|default('text') %}
{%- set type = type|default('text') -%}
<input type="{{ type }}" {{ block('widget_attributes') }} value="{{ value }}" rel="theme" />
{% endspaceless %}
{% endblock form_widget_simple %}
{%- endblock form_widget_simple %}

View File

@ -159,7 +159,7 @@ class TranslationUpdateCommandTest extends TestCase
->expects($this->any())
->method('getFormats')
->will(
$this->returnValue(['xlf', 'yml'])
$this->returnValue(['xlf', 'yml', 'yaml'])
);
if (null === $kernel) {

View File

@ -365,7 +365,7 @@ class DebugClassLoader
$finalOrInternal = false;
foreach (['final', 'internal'] as $annotation) {
if (false !== \strpos($doc, $annotation) && preg_match('#\n\s+\* @'.$annotation.'(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$)#s', $doc, $notice)) {
if (false !== \strpos($doc, $annotation) && preg_match('#\n\s+\* @'.$annotation.'(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$|\r?\n)#s', $doc, $notice)) {
$message = isset($notice[1]) ? preg_replace('#\.?\r?\n( \*)? *(?= |\r?\n|$)#', '', $notice[1]) : '';
self::${$annotation.'Methods'}[$class][$method->name] = [$class, $message];
$finalOrInternal = true;

View File

@ -13,6 +13,8 @@ class FinalMethod
/**
* @final
*
* @return int
*/
public function finalMethod2()
{

View File

@ -138,7 +138,7 @@ class Container implements ResettableContainerInterface
/**
* Sets a service.
*
* Setting a service to null resets the service: has() returns false and get()
* Setting a synthetic service to null resets it: has() returns false and get()
* behaves in the same way as if the service was never created.
*
* @param string $id The service identifier

View File

@ -102,9 +102,9 @@ class FormPass implements CompilerPassInterface
} elseif (method_exists($serviceDefinition->getClass(), 'getExtendedTypes')) {
$extendsTypes = false;
$typeExtensionsClasses[] = $serviceDefinition->getClass();
foreach ($serviceDefinition->getClass()::getExtendedTypes() as $extendedType) {
$typeExtensions[$extendedType][] = new Reference($serviceId);
$typeExtensionsClasses[] = $serviceDefinition->getClass();
$extendsTypes = true;
}

View File

@ -20,12 +20,14 @@ use Symfony\Component\Form\Forms;
*/
abstract class FormIntegrationTestCase extends TestCase
{
use TestCaseSetUpTearDownTrait;
/**
* @var FormFactoryInterface
*/
protected $factory;
protected function setUp()
private function doSetUp()
{
$this->factory = Forms::createFormFactoryBuilder()
->addExtensions($this->getExtensions())

View File

@ -0,0 +1,82 @@
<?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\Component\Form\Test;
use PHPUnit\Framework\TestCase;
// Auto-adapt to PHPUnit 8 that added a `void` return-type to the setUp/tearDown methods
if (method_exists(\ReflectionMethod::class, 'hasReturnType') && (new \ReflectionMethod(TestCase::class, 'tearDown'))->hasReturnType()) {
eval('
namespace Symfony\Component\Form\Test;
/**
* @internal
*/
trait TestCaseSetUpTearDownTrait
{
private function doSetUp(): void
{
}
private function doTearDown(): void
{
}
protected function setUp(): void
{
$this->doSetUp();
}
protected function tearDown(): void
{
$this->doTearDown();
}
}
');
} else {
/**
* @internal
*/
trait TestCaseSetUpTearDownTrait
{
/**
* @return void
*/
private function doSetUp()
{
}
/**
* @return void
*/
private function doTearDown()
{
}
/**
* @return void
*/
protected function setUp()
{
$this->doSetUp();
}
/**
* @return void
*/
protected function tearDown()
{
$this->doTearDown();
}
}
}

View File

@ -17,6 +17,8 @@ use Symfony\Component\Form\Test\Traits\ValidatorExtensionTrait;
abstract class TypeTestCase extends FormIntegrationTestCase
{
use TestCaseSetUpTearDownTrait;
/**
* @var FormBuilder
*/
@ -27,7 +29,7 @@ abstract class TypeTestCase extends FormIntegrationTestCase
*/
protected $dispatcher;
protected function setUp()
private function doSetUp()
{
parent::setUp();
@ -35,7 +37,7 @@ abstract class TypeTestCase extends FormIntegrationTestCase
$this->builder = new FormBuilder('', null, $this->dispatcher, $this->factory);
}
protected function tearDown()
private function doTearDown()
{
if (\in_array(ValidatorExtensionTrait::class, class_uses($this))) {
$this->validator = null;

View File

@ -40,7 +40,7 @@ class Logger extends AbstractLogger
public function __construct(string $minLevel = null, $output = 'php://stderr', callable $formatter = null)
{
if (null === $minLevel) {
$minLevel = LogLevel::WARNING;
$minLevel = 'php://stdout' === $output || 'php://stderr' === $output ? LogLevel::CRITICAL : LogLevel::WARNING;
if (isset($_ENV['SHELL_VERBOSITY']) || isset($_SERVER['SHELL_VERBOSITY'])) {
switch ((int) (isset($_ENV['SHELL_VERBOSITY']) ? $_ENV['SHELL_VERBOSITY'] : $_SERVER['SHELL_VERBOSITY'])) {

View File

@ -38,6 +38,21 @@ class AmqpSenderTest extends TestCase
$sender->send($envelope);
}
public function testItSendsTheEncodedMessageWithoutHeaders()
{
$envelope = new Envelope(new DummyMessage('Oy'));
$encoded = ['body' => '...'];
$serializer = $this->getMockBuilder(SerializerInterface::class)->getMock();
$serializer->method('encode')->with($envelope)->willReturnOnConsecutiveCalls($encoded);
$connection = $this->getMockBuilder(Connection::class)->disableOriginalConstructor()->getMock();
$connection->expects($this->once())->method('publish')->with($encoded['body'], []);
$sender = new AmqpSender($connection, $serializer);
$sender->send($envelope);
}
/**
* @expectedException \Symfony\Component\Messenger\Exception\TransportException
*/

View File

@ -43,7 +43,7 @@ class AmqpSender implements SenderInterface
$encodedMessage = $this->serializer->encode($envelope);
try {
$this->connection->publish($encodedMessage['body'], $encodedMessage['headers']);
$this->connection->publish($encodedMessage['body'], $encodedMessage['headers'] ?? []);
} catch (\AMQPException $e) {
throw new TransportException($e->getMessage(), 0, $e);
}

View File

@ -118,7 +118,7 @@ class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTyp
}
if (
$context['enable_constructor_extraction'] ?? $this->enableConstructorExtraction &&
($context['enable_constructor_extraction'] ?? $this->enableConstructorExtraction) &&
$fromConstructor = $this->extractFromConstructor($class, $property)
) {
return $fromConstructor;

View File

@ -313,4 +313,29 @@ class ReflectionExtractorTest extends TestCase
[NotInstantiable::class, 'foo', false],
];
}
/**
* @dataProvider constructorTypesProvider
*/
public function testExtractTypeConstructor(string $class, string $property, array $type = null)
{
/* Check that constructor extractions works by default, and if passed in via context.
Check that null is returned if constructor extraction is disabled */
$this->assertEquals($type, $this->extractor->getTypes($class, $property, []));
$this->assertEquals($type, $this->extractor->getTypes($class, $property, ['enable_constructor_extraction' => true]));
$this->assertNull($this->extractor->getTypes($class, $property, ['enable_constructor_extraction' => false]));
}
public function constructorTypesProvider(): array
{
return [
// php71 dummy has following constructor: __construct(string $string, int $intPrivate)
[Php71Dummy::class, 'string', [new Type(Type::BUILTIN_TYPE_STRING, false)]],
[Php71Dummy::class, 'intPrivate', [new Type(Type::BUILTIN_TYPE_INT, false)]],
// Php71DummyExtended2 adds int $intWithAccessor
[Php71DummyExtended2::class, 'intWithAccessor', [new Type(Type::BUILTIN_TYPE_INT, false)]],
[Php71DummyExtended2::class, 'intPrivate', [new Type(Type::BUILTIN_TYPE_INT, false)]],
[DefaultValue::class, 'foo', null],
];
}
}

View File

@ -310,10 +310,30 @@
<source>This value does not match the expected {{ charset }} charset.</source>
<target>该值不符合 {{ charset }} 编码。</target>
</trans-unit>
<trans-unit id="81">
<source>This is not a valid Business Identifier Code (BIC).</source>
<target>这不是有效的业务标识符代码BIC)。</target>
</trans-unit>
<trans-unit id="82">
<source>Error</source>
<target>错误</target>
</trans-unit>
<trans-unit id="83">
<source>This is not a valid UUID.</source>
<target>这不是有效的UUID。</target>
</trans-unit>
<trans-unit id="84">
<source>This value should be a multiple of {{ compared_value }}.</source>
<target>此值应为 {{ compared_value }} 的倍数。</target>
</trans-unit>
<trans-unit id="85">
<source>This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}.</source>
<target>此业务标识符代码BIC与IBAN {{ iban }} 无关。</target>
</trans-unit>
<trans-unit id="86">
<source>This value should be valid JSON.</source>
<target>该值应该是有效的JSON。</target>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -30,6 +30,8 @@ use Symfony\Contracts\Translation\TranslatorInterface;
*/
abstract class ConstraintValidatorTestCase extends TestCase
{
use TestCaseSetUpTearDownTrait;
/**
* @var ExecutionContextInterface
*/
@ -49,7 +51,7 @@ abstract class ConstraintValidatorTestCase extends TestCase
protected $constraint;
protected $defaultTimezone;
protected function setUp()
private function doSetUp()
{
$this->group = 'MyGroup';
$this->metadata = null;
@ -71,7 +73,7 @@ abstract class ConstraintValidatorTestCase extends TestCase
$this->setDefaultTimezone('UTC');
}
protected function tearDown()
private function doTearDown()
{
$this->restoreDefaultTimezone();
}

View File

@ -0,0 +1,82 @@
<?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\Component\Validator\Test;
use PHPUnit\Framework\TestCase;
// Auto-adapt to PHPUnit 8 that added a `void` return-type to the setUp/tearDown methods
if (method_exists(\ReflectionMethod::class, 'hasReturnType') && (new \ReflectionMethod(TestCase::class, 'tearDown'))->hasReturnType()) {
eval('
namespace Symfony\Component\Validator\Test;
/**
* @internal
*/
trait TestCaseSetUpTearDownTrait
{
private function doSetUp(): void
{
}
private function doTearDown(): void
{
}
protected function setUp(): void
{
$this->doSetUp();
}
protected function tearDown(): void
{
$this->doTearDown();
}
}
');
} else {
/**
* @internal
*/
trait TestCaseSetUpTearDownTrait
{
/**
* @return void
*/
private function doSetUp()
{
}
/**
* @return void
*/
private function doTearDown()
{
}
/**
* @return void
*/
protected function setUp()
{
$this->doSetUp();
}
/**
* @return void
*/
protected function tearDown()
{
$this->doTearDown();
}
}
}