8000 Merge branch '3.4' into 4.0 · symfony/symfony@0dc6acb · GitHub
[go: up one dir, main page]

Skip to content
8000

Commit 0dc6acb

Browse files
Merge branch '3.4' into 4.0
* 3.4: [Translation] Process multiple segments within a single unit. Document the container.autowiring.strict_mode option fix custom radios/inputs for checkbox/radio type Another PR template tweak [FrameworkBundle] Add missing XML config for circular_reference_handler. Add tests. fix CS [PropertyInfo] ReflectionExtractor: give a chance to other extractors if no properties Clean calls to http_build_query() [WebProfilerBundle] limit ajax request to 100 and remove the last one Add support for URL-like DSNs for the PdoSessionHandler [HttpFoundation] Fix missing "throw" in JsonResponse Improve the documentation of Suppress warning from sapi_windows_vt100_support on stream other than STDIO removed extra-verbose comments Fixes #26136: Avoid emitting warning in hasParameterOption() Added a README entry to the PR template [HttpFoundation] Add x-zip-compressed to MimeTypeExtensionGuesser. [DI] Add null check for removeChild
2 parents 389efc0 + 4334459 commit 0dc6acb

File tree

27 files changed

+292
-52
lines changed

27 files changed

+292
-52
lines changed

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,18 @@
33
| Branch? | master for features / 2.7 up to 4.0 for bug fixes <!-- see below -->
44
| Bug fix? | yes/no
55
| New feature? | yes/no <!-- don't forget to update src/**/CHANGELOG.md files -->
6-
| BC breaks? | yes/no
6+
| BC breaks? | no <!-- see https://symfony.com/bc -->
77
| Deprecations? | yes/no <!-- don't forget to update UPGRADE-*.md files -->
8-
| Tests pass? | yes/no
9-
| Fixed tickets | #... <!-- #-prefixed issue number(s), if any -->
8+
| Tests pass? | yes <!-- please add some, will be required by reviewers -->
9+
| Fixed tickets | #... <!-- #-prefixed issue number(s), if any -->
1010
| License | MIT
11-
| Doc PR | symfony/symfony-docs#... <!--highly recommended for new features-->
11+
| Doc PR | symfony/symfony-docs#... <!-- required for new features -->
1212

1313
<!--
14-
- Bug fixes must be submitted against the lowest branch where they apply
15-
(lowest branches are regularly merged to upper ones so they get the fixes too).
16-
- Features and deprecations must be submitted against the master branch.
17-
- Replace this comment by a description of what your PR is solving.
14+
Write a short README entry for your feature/bugfix here (replace this comment block.)
15+
This will help people understand your PR and can be used as a start of the Doc PR.
16+
Additionally:
17+
- Bug fixes must be submitted against the lowest branch where they apply
18+
(lowest branches are regularly merged to upper ones so they get the fixes too).
19+
- Features and deprecations must be submitted against the master branch.
1820
-->

UPGRADE-4.0.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,18 @@ DependencyInjection
163163
autowire: true
164164
```
165165
166-
* Autowiring services based on the types they implement is not supported anymore. Rename (or alias) your services to their FQCN id to make them autowirable.
166+
* Autowiring services based on the types they implement is not supported anymore.
167+
It will only look for an alias or a service id that matches a given FQCN.
168+
Rename (or alias) your services to their FQCN id to make them autowirable.
169+
In 3.4, you can activate this behavior instead of having deprecation messages
170+
by setting the following parameter:
171+
172+
```yml
173+
parameters:
174+
container.autowiring.strict_mode: true
175+
```
176+
177+
From 4.0, you can remove it as it's the default behavior and the parameter is not handled anymore.
167178
168179
* `_defaults` and `_instanceof` are now reserved service names in Yaml configurations. Please rename any services with that names.
169180

src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,9 @@
190190
{% block checkbox_radio_label -%}
191191
{#- Do not display the label if widget is not defined in order to prevent double label rendering -#}
192192
{%- if widget is defined -%}
193-
{%- if parent_label_class is defined and ('checkbox-custom' in parent_label_class or 'radio-custom' in parent_label_class) -%}
193+
{% set is_parent_custom = parent_label_class is defined and ('checkbox-custom' in parent_label_class or 'radio-custom' in parent_label_class) %}
194+
{% set is_custom = label_attr.class is defined and ('checkbox-custom' in label_attr.class or 'radio-custom' in label_attr.class) %}
195+
{%- if is_parent_custom or is_custom -%}
194196
{%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' custom-control-label')|trim}) -%}
195197
{%- else %}
196198
{%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' form-check-label')|trim}) -%}

src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@
230230
<xsd:attribute name="cache" type="xsd:string" />
231231
<xsd:attribute name="enable-annotations" type="xsd:boolean" />
232232
<xsd:attribute name="name-converter" type="xsd:string" />
233+
<xsd:attribute name="circular-reference-handler" type="xsd:string" />
233234
</xsd:complexType>
234235

235236
<xsd:complexType name="property_info">

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
'enabled' => true,
6969
'enable_annotations' => true,
7070
'name_converter' => 'serializer.name_converter.camel_case_to_snake_case',
71+
'circular_reference_handler' => 'my.circular.reference.handler',
7172
),
7273
'property_info' => true,
7374
'ide' => 'file%%link%%format',

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
</framework:translator>
4242
<framework:validation enabled="true" />
4343
<framework:annotations cache="file" debug="true" file-cache-dir="%kernel.cache_dir%/annotations" />
44-
<framework:serializer enabled="true" enable-annotations="true" name-converter="serializer.name_converter.camel_case_to_snake_case" />
44+
<framework:serializer enabled="true" enable-annotations="true" name-converter="serializer.name_converter.camel_case_to_snake_case" circular-reference-handler="my.circular.reference.handler" />
4545
<framework:property-info />
4646
</framework:config>
4747
</container>

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,10 @@ framework:
5151
debug: true
5252
file_cache_dir: '%kernel.cache_dir%/annotations'
5353
serializer:
54-
enabled: true
55-
enable_annotations: true
56-
name_converter: serializer.name_converter.camel_case_to_snake_case
54+
enabled: true
55+
enable_annotations: true
56+
name_converter: serializer.name_converter.camel_case_to_snake_case
57+
circular_reference_handler: my.circular.reference.handler
5758
property_info: ~
5859
ide: file%%link%%format
5960
request:

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,7 @@ public function testSerializerEnabled()
774774
$this->assertNull($container->getDefinition('serializer.mapping.class_metadata_factory')->getArgument(1));
775775
$this->assertEquals(new Reference('serializer.name_converter.camel_case_to_snake_case'), $container->getDefinition('serializer.normalizer.object')->getArgument(1));
776776
$this->assertEquals(new Reference('property_info', ContainerBuilder::IGNORE_ON_INVALID_REFERENCE), $container->getDefinition('serializer.normalizer.object')->getArgument(3));
777+
$this->assertEquals(array('setCircularReferenceHandler', array(new Reference('my.circular.reference.handler'))), $container->getDefinition('serializer.normalizer.object')->getMethodCalls()[0]);
777778
}
778779

779780
public function testRegisterSerializerExtractor()

src/Symfony/Component/Console/Input/ArgvInput.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ public function hasParameterOption($values, $onlyParams = false)
281281
// For long options, test for '--option=' at beginning
282282
// For short options, test for '-o' at beginning
283283
$leading = 0 === strpos($value, '--') ? $value.'=' : $value;
284-
if ($token === $value || 0 === strpos($token, $leading)) {
284+
if ($token === $value || '' !== $leading && 0 === strpos($token, $leading)) {
285285
return true;
286286
}
287287
}
@@ -312,7 +312,7 @@ public function getParameterOption($values, $default = false, $onlyParams = fals
312312
// For long options, test for '--option=' at beginning
313313
// For short options, test for '-o' at beginning
314314
$leading = 0 === strpos($value, '--') ? $value.'=' : $value;
315-
if (0 === strpos($token, $leading)) {
315+
if ('' !== $leading && 0 === strpos($token, $leading)) {
316316
return substr($token, strlen($leading));
317317
}
318318
}

src/Symfony/Component/Console/Output/StreamOutput.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ protected function hasColorSupport()
9292
{
9393
if (DIRECTORY_SEPARATOR === '\\') {
9494
return
95-
function_exists('sapi_windows_vt100_support') && sapi_windows_vt100_support($this->stream)
95+
function_exists('sapi_windows_vt100_support') && @sapi_windows_vt100_support($this->stream)
9696
|| '10.0.10586' === PHP_WINDOWS_VERSION_MAJOR.'.'.PHP_WINDOWS_VERSION_MINOR.'.'.PHP_WINDOWS_VERSION_BUILD
9797
|| false !== getenv('ANSICON')
9898
|| 'ON' === getenv('ConEmuANSI')

src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,19 @@ public function testHasParameterOptionEdgeCasesAndLimitations()
370370
$this->assertFalse($input->hasParameterOption('-fh'), '->hasParameterOption() returns true if the given short option is in the raw input');
371371
}
372372

373+
public function testNoWarningOnInvalidParameterOption()
374+
{
375+
$input = new ArgvInput(array('cli.php', '-edev'));
376+
377+
$this->assertTrue($input->hasParameterOption(array('-e', '')));
378+
// No warning thrown
379+
$this->assertFalse($input->hasParameterOption(array('-m', '')));
380+
381+
$this->assertEquals('dev', $input->getParameterOption(array('-e', '')));
382+
// No warning thrown
383+
$this->assertFalse($input->getParameterOption(array('-m', '')));
384+
}
385+
373386
public function testToString()
374387
{
375388
$input = new ArgvInput(array('cli.php', '-f', 'foo'));

src/Symfony/Component/DomCrawler/Form.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ public function getUri()
209209
parse_str($query, $currentParameters);
210210
}
211211

212-
$queryString = http_build_query(array_merge($currentParameters, $this->getValues()), null, '&');
212+
$queryString = http_build_query(array_merge($currentParameters, $this->getValues()), '', '&');
213213

214214
$pos = strpos($uri, '?');
215215
$base = false === $pos ? $uri : substr($uri, 0, $pos);

src/Symfony/Component/Filesystem/Filesystem.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -524,13 +524,18 @@ public function makePathRelative($endPath, $startPath)
524524
/**
525525
* Mirrors a directory to another.
526526
*
527+
* Copies files and directories from the origin directory into the target directory. By default:
528+
*
529+
* - existing files in the target directory will be overwritten, except if they are newer (see the `override` option)
530+
* - files in the target directory that do not exist in the source directory will not be deleted (see the `delete` option)
531+
*
527532
* @param string $originDir The origin directory
528533
* @param string $targetDir The target directory
529-
* @param \Traversable $iterator A Traversable instance
534+
* @param \Traversable $iterator Iterator that filters which files and directories to copy
530535
* @param array $options An array of boolean options
531536
* Valid options are:
532-
* - $options['override'] Whether to override an existing file on copy or not (see copy())
533-
* - $options['copy_on_windows'] Whether to copy files instead of links on Windows (see symlink())
537+
* - $options['override'] If true, target files newer than origin files are overwritten (see copy(), defaults to false)
538+
* - $options['copy_on_windows'] Whether to copy files instead of links on Windows (see symlink(), defaults to false)
534539
* - $options['delete'] Whether to delete files that are not in the source directory (defaults to false)
535540
*
536541
* @throws IOException When file type is unknown

src/Symfony/Component/Form/Tests/AbstractBootstrap4LayoutTest.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,7 @@ public function testSingleChoiceExpandedWithPlaceholderWithoutTranslation()
547547
]
548548
/following-sibling::div
549549
[@class="form-check"]
550-
[
550+
[
551551
./input[@type="radio"][@name="name"][@id="name_0"][@checked]
552552
/following-sibling::label
553553
[.="Choice&A"]
@@ -959,8 +959,7 @@ public function testPercent()
959959
./span
960960
[@class="input-group-text"]
961961
[contains(.., "%")]
962-
]
963-
962+
]
964963
]
965964
'
966965
);

src/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeExtensionGuesser.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,7 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface
599599
'application/x-xliff+xml' => 'xlf',
600600
'application/x-xpinstall' => 'xpi',
601601
'application/x-xz' => 'xz',
602+
'application/x-zip-compressed' => 'zip',
602603
'application/x-zmachine' => 'z1',
603604
'application/xaml+xml' => 'xaml',
604605
'application/xcap-diff+xml' => 'xdf',

src/Symfony/Component/HttpFoundation/Request.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -524,7 +524,7 @@ public function __toString()
524524
*/
525525
public function overrideGlobals()
526526
{
527-
$this->server->set('QUERY_STRING', static::normalizeQueryString(http_build_query($this->query->all(), null, '&')));
527+
$this->server->set('QUERY_STRING', static::normalizeQueryString(http_build_query($this->query->all(), '', '&')));
528528

529529
$_GET = $this->query->all();
530530
$_POST = $this->request->all();

src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ class PdoSessionHandler extends AbstractSessionHandler
164164
* * db_connection_options: An array of driver-specific connection options [default: array()]
165165
* * lock_mode: The strategy for locking, see constants [default: LOCK_TRANSACTIONAL]
166166
*
167-
* @param \PDO|string|null $pdoOrDsn A \PDO instance or DSN string or null
167+
* @param \PDO|string|null $pdoOrDsn A \PDO instance or DSN string or URL string or null
168168
* @param array $options An associative array of options
169169
*
170170
* @throws \InvalidArgumentException When PDO error mode is not PDO::ERRMODE_EXCEPTION
@@ -178,6 +178,8 @@ public function __construct($pdoOrDsn = null, array $options = array())
178178

179179
$this->pdo = $pdoOrDsn;
180180
$this->driver = $this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME);
181+
} elseif (is_string($pdoOrDsn) && false !== strpos($pdoOrDsn, '://')) {
182+
$this->dsn = $this->buildDsnFromUrl($pdoOrDsn);
181183
} else {
182184
$this->dsn = $pdoOrDsn;
183185
}
@@ -431,6 +433,102 @@ private function connect($dsn)
431433
$this->driver = $this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME);
432434
}
433435

436+
/**
437+
* Builds a PDO DSN from a URL-like connection string.
438+
*
439+
* @param string $dsnOrUrl
440+
*
441+
* @return string
442+
*
443+
* @todo implement missing support for oci DSN (which look totally different from other PDO ones)
4 F438 44+
*/
445+
private function buildDsnFromUrl($dsnOrUrl)
446+
{
447+
// (pdo_)?sqlite3?:///... => (pdo_)?sqlite3?://localhost/... or else the URL will be invalid
448+
$url = preg_replace('#^((?:pdo_)?sqlite3?):///#', '$1://localhost/', $dsnOrUrl);
449+
450+
$params = parse_url($url);
451+
452+
if (false === $params) {
453+
return $dsnOrUrl; // If the URL is not valid, let's assume it might be a DSN already.
454+
}
455+
456+
$params = array_map('rawurldecode', $params);
457+
458+
// Override the default username and password. Values passed through options will still win over these in the constructor.
459+
if (isset($params['user'])) {
460+
$this->username = $params['user'];
461+
}
462+
463+
if (isset($params['pass'])) {
464+
$this->password = $params['pass'];
465+
}
466+
467+
if (!isset($params['scheme'])) {
468+
throw new \InvalidArgumentException('URLs without scheme are not supported to configure the PdoSessionHandler');
469+
}
470+
471+
$driverAliasMap = array(
472+
'mssql' => 'sqlsrv',
473+
'mysql2' => 'mysql', // Amazon RDS, for some weird reason
474+
'postgres' => 'pgsql',
475+
'postgresql' => 'pgsql',
476+
'sqlite3' => 'sqlite',
477+
);
478+
479+
$driver = isset($driverAliasMap[$params['scheme']]) ? $driverAliasMap[$params['scheme']] : $params['scheme'];
480+
481+
// Doctrine DBAL supports passing its internal pdo_* driver names directly too (allowing both dashes and underscores). This allows supporting the same here.
482+
if (0 === strpos($driver, 'pdo_') || 0 === strpos($driver, 'pdo-')) {
483+
$driver = substr($driver, 4);
484+
}
485+
486+
switch ($driver) {
487+
case 'mysql':
488+
case 'pgsql':
489+
$dsn = $driver.':';
490+
491+
if (isset($params['host']) && '' !== $params['host']) {
492+
$dsn .= 'host='.$params['host'].';';
493+
}
494+
495+
if (isset($params['port']) && '' !== $params['port']) {
496+
$dsn .= 'port='.$params['port'].';';
497+
}
498+
499+
if (isset($params['path'])) {
500+
$dbName = substr($params['path'], 1); // Remove the leading slash
501+
$dsn .= 'dbname='.$dbName.';';
502+
}
503+
504+
return $dsn;
505+
506+
case 'sqlite':
507+
return 'sqlite:'.substr($params['path'], 1);
508+
509+
case 'sqlsrv':
510+
$dsn = 'sqlsrv:server=';
511+
512+
if (isset($params['host'])) {
513+
$dsn .= $params['host'];
514+
}
515+
516+
if (isset($params['port']) && '' !== $params['port']) {
517+
$dsn .= ','.$params['port'];
518+
}
519+
520+
if (isset($params['path'])) {
521+
$dbName = substr($params['path'], 1); // Remove the leading slash
522+
$dsn .= ';Database='.$dbName;
523+
}
524+
525+
return $dsn;
526+
527+
default:
528+
throw new \InvalidArgumentExcep 10000 tion(sprintf('The scheme "%s" is not supported by the PdoSessionHandler URL configuration. Pass a PDO DSN directly.', $params['scheme']));
529+
}
530+
}
531+
434532
/**
435533
* Helper method to begin a transaction.
436534
*

src/Symfony/Component/HttpFoundation/Tests/RequestTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2177,7 +2177,7 @@ class RequestContentProxy extends Request
21772177
{
21782178
public function getContent($asResource = false)
21792179
{
2180-
return http_build_query(array('_method' => 'PUT', 'content' => 'mycontent'));
2180+
return http_build_query(array('_method' => 'PUT', 'content' => 'mycontent'), '', '&');
21812181
}
21822182
}
21832183

src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,41 @@ public function testGetConnectionConnectsIfNeeded()
317317
$this->assertInstanceOf('\PDO', $method->invoke($storage));
318318
}
319319

320+
/**
321+
* @dataProvider provideUrlDsnPairs
322+
*/
323+
public function testUrlDsn($url, $expectedDsn, $expectedUser = null, $expectedPassword = null)
324+
{
325+
$storage = new PdoSessionHandler($url);
326+
327+
$this->assertAttributeEquals($expectedDsn, 'dsn', $storage);
328+
329+
if (null !== $expectedUser) {
330+
$this->assertAttributeEquals($expectedUser, 'username', $storage);
331+
}
332+
333+
if (null !== $expectedPassword) {
334+
$this->assertAttributeEquals($expectedPassword, 'password', $storage);
335+
}
336+
}
337+
338+
public function provideUrlDsnPairs()
339+
{
340+
yield array('mysql://localhost/test', 'mysql:host=localhost;dbname=test;');
341+
yield array('mysql://localhost:56/test', 'mysql:host=localhost;port=56;dbname=test;');
342+
yield array('mysql2://root:pwd@localhost/test', 'mysql:host=localhost;dbname=test;', 'root', 'pwd');
343+
yield array('postgres://localhost/test', 'pgsql:host=localhost;dbname=test;');
344+
yield array('postgresql://localhost:5634/test', 'pgsql:host=localhost;port=5634;dbname=test;');
345+
yield array('postgres://root:pwd@localhost/test', 'pgsql:host=localhost;dbname=test;', 'root', 'pwd');
346+
yield 'sqlite relative path' => array('sqlite://localhost/tmp/test', 'sqlite:tmp/test');
347+
yield 'sqlite absolute path' => array('sqlite://localhost//tmp/test', 'sqlite:/tmp/test');
348+
yield 'sqlite relative path without host' => array('sqlite:///tmp/test', 'sqlite:tmp/test');
349+
yield 'sqlite absolute path without host' => array('sqlite3:////tmp/test', 'sqlite:/tmp/test');
350+
yield array('sqlite://localhost/:memory:', 'sqlite::memory:');
351+
yield array('mssql://localhost/test', 'sqlsrv:server=localhost;Database=test');
352+
yield array('mssql://localhost:56/test', 'sqlsrv:server=localhost,56;Database=test');
353+
}
354+
320355
private function createStream($content)
321356
{
322357
$stream = tmpfile();

src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ public function getProperties($class, array $context = array())
9292
$properties[$propertyName] = $propertyName;
9393
}
9494

95-
return array_values($properties);
95+
return $properties ? array_values($properties) : null;
9696
}
9797

9898
/**

0 commit comments

Comments
 (0)
0