Merge branch '4.4' into 5.0
* 4.4: (26 commits) [HttpClient] NativeHttpClient should not send >1.1 protocol version [HttpClient] fix support for non-blocking resource streams [Mailer] Make sure you can pass custom headers to Mailgun [Mailer] Remove line breaks in email attachment content Update links to documentation [Validator] Add the missing translations for the Arabic (ar) locale ensure to expect no validation for the right reasons [Security-Guard] fixed 35203 missing name tag in param docblock [HttpClient] fix casting responses to PHP streams [PhpUnitBridge] Add test case for @expectedDeprecation annotation [PhpUnitBridge][SymfonyTestsListenerTrait] Remove $testsWithWarnings stack [Mailer] Fix addresses management in Sendgrid API payload [Mailer][MailchimpBridge] Fix missing attachments when sending via Mandrill API [Mailer][MailchimpBridge] Fix incorrect sender address when sender has name [HttpClient] fix capturing SSL certificates with NativeHttpClient Update year in license files [TwigBridge][Form] Added missing help messages in form themes Update year in license files Update year in license files fix version when "anonymous: lazy" was introduced ...
This commit is contained in:
commit
581b439931
2
LICENSE
2
LICENSE
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2004-2019 Fabien Potencier
|
Copyright (c) 2004-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2004-2019 Fabien Potencier
|
Copyright (c) 2004-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2004-2019 Fabien Potencier
|
Copyright (c) 2004-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2014-2019 Fabien Potencier
|
Copyright (c) 2014-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -47,11 +47,6 @@ class SymfonyTestsListenerForV5 extends \PHPUnit_Framework_BaseTestListener
|
|||||||
$this->trait->startTest($test);
|
$this->trait->startTest($test);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addWarning(\PHPUnit_Framework_Test $test, \PHPUnit_Framework_Warning $e, $time)
|
|
||||||
{
|
|
||||||
$this->trait->addWarning($test, $e, $time);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function endTest(\PHPUnit_Framework_Test $test, $time)
|
public function endTest(\PHPUnit_Framework_Test $test, $time)
|
||||||
{
|
{
|
||||||
$this->trait->endTest($test, $time);
|
$this->trait->endTest($test, $time);
|
||||||
|
@ -52,11 +52,6 @@ class SymfonyTestsListenerForV6 extends BaseTestListener
|
|||||||
$this->trait->startTest($test);
|
$this->trait->startTest($test);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addWarning(Test $test, Warning $e, $time)
|
|
||||||
{
|
|
||||||
$this->trait->addWarning($test, $e, $time);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function endTest(Test $test, $time)
|
public function endTest(Test $test, $time)
|
||||||
{
|
{
|
||||||
$this->trait->endTest($test, $time);
|
$this->trait->endTest($test, $time);
|
||||||
|
@ -55,11 +55,6 @@ class SymfonyTestsListenerForV7 implements TestListener
|
|||||||
$this->trait->startTest($test);
|
$this->trait->startTest($test);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addWarning(Test $test, Warning $e, float $time): void
|
|
||||||
{
|
|
||||||
$this->trait->addWarning($test, $e, $time);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function endTest(Test $test, float $time): void
|
public function endTest(Test $test, float $time): void
|
||||||
{
|
{
|
||||||
$this->trait->endTest($test, $time);
|
$this->trait->endTest($test, $time);
|
||||||
|
@ -40,7 +40,6 @@ class SymfonyTestsListenerTrait
|
|||||||
private $expectedDeprecations = array();
|
private $expectedDeprecations = array();
|
||||||
private $gatheredDeprecations = array();
|
private $gatheredDeprecations = array();
|
||||||
private $previousErrorHandler;
|
private $previousErrorHandler;
|
||||||
private $testsWithWarnings;
|
|
||||||
private $reportUselessTests;
|
private $reportUselessTests;
|
||||||
private $error;
|
private $error;
|
||||||
private $runsInSeparateProcess = false;
|
private $runsInSeparateProcess = false;
|
||||||
@ -112,7 +111,6 @@ class SymfonyTestsListenerTrait
|
|||||||
public function startTestSuite($suite)
|
public function startTestSuite($suite)
|
||||||
{
|
{
|
||||||
$suiteName = $suite->getName();
|
$suiteName = $suite->getName();
|
||||||
$this->testsWithWarnings = array();
|
|
||||||
|
|
||||||
foreach ($suite->tests() as $test) {
|
foreach ($suite->tests() as $test) {
|
||||||
if (!($test instanceof \PHPUnit\Framework\TestCase || $test instanceof TestCase)) {
|
if (!($test instanceof \PHPUnit\Framework\TestCase || $test instanceof TestCase)) {
|
||||||
@ -236,13 +234,6 @@ class SymfonyTestsListenerTrait
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addWarning($test, $e, $time)
|
|
||||||
{
|
|
||||||
if ($test instanceof \PHPUnit\Framework\TestCase || $test instanceof TestCase) {
|
|
||||||
$this->testsWithWarnings[$test->getName()] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function endTest($test, $time)
|
public function endTest($test, $time)
|
||||||
{
|
{
|
||||||
if (class_exists(DebugClassLoader::class, false)) {
|
if (class_exists(DebugClassLoader::class, false)) {
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
<?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\Bridge\PhpUnit\Tests;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
final class ExpectedDeprecationAnnotationTest extends TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Do not remove this test in the next major versions.
|
||||||
|
*
|
||||||
|
* @group legacy
|
||||||
|
*
|
||||||
|
* @expectedDeprecation foo
|
||||||
|
*/
|
||||||
|
public function testOne()
|
||||||
|
{
|
||||||
|
@trigger_error('foo', E_USER_DEPRECATED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do not remove this test in the next major versions.
|
||||||
|
*
|
||||||
|
* @group legacy
|
||||||
|
*
|
||||||
|
* @expectedDeprecation foo
|
||||||
|
* @expectedDeprecation bar
|
||||||
|
*/
|
||||||
|
public function testMany()
|
||||||
|
{
|
||||||
|
@trigger_error('foo', E_USER_DEPRECATED);
|
||||||
|
@trigger_error('bar', E_USER_DEPRECATED);
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2004-2019 Fabien Potencier
|
Copyright (c) 2004-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2004-2019 Fabien Potencier
|
Copyright (c) 2004-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -64,6 +64,7 @@ col-sm-10
|
|||||||
<div class="{{ block('form_label_class') }}"></div>{#--#}
|
<div class="{{ block('form_label_class') }}"></div>{#--#}
|
||||||
<div class="{{ block('form_group_class') }}">
|
<div class="{{ block('form_group_class') }}">
|
||||||
{{- form_widget(form) -}}
|
{{- form_widget(form) -}}
|
||||||
|
{{- form_help(form) -}}
|
||||||
{{- form_errors(form) -}}
|
{{- form_errors(form) -}}
|
||||||
</div>{#--#}
|
</div>{#--#}
|
||||||
</div>
|
</div>
|
||||||
|
@ -148,6 +148,7 @@
|
|||||||
{% block checkbox_row -%}
|
{% block checkbox_row -%}
|
||||||
<div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group' ~ (not valid ? ' has-error'))|trim})} %}{{ block('attributes') }}{% endwith %}>
|
<div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group' ~ (not valid ? ' has-error'))|trim})} %}{{ block('attributes') }}{% endwith %}>
|
||||||
{{- form_widget(form) -}}
|
{{- form_widget(form) -}}
|
||||||
|
{{- form_help(form) -}}
|
||||||
{{- form_errors(form) -}}
|
{{- form_errors(form) -}}
|
||||||
</div>
|
</div>
|
||||||
{%- endblock checkbox_row %}
|
{%- endblock checkbox_row %}
|
||||||
@ -155,6 +156,7 @@
|
|||||||
{% block radio_row -%}
|
{% block radio_row -%}
|
||||||
<div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group' ~ (not valid ? ' has-error'))|trim})} %}{{ block('attributes') }}{% endwith %}>
|
<div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group' ~ (not valid ? ' has-error'))|trim})} %}{{ block('attributes') }}{% endwith %}>
|
||||||
{{- form_widget(form) -}}
|
{{- form_widget(form) -}}
|
||||||
|
{{- form_help(form) -}}
|
||||||
{{- form_errors(form) -}}
|
{{- form_errors(form) -}}
|
||||||
</div>
|
</div>
|
||||||
{%- endblock radio_row %}
|
{%- endblock radio_row %}
|
||||||
|
@ -311,6 +311,7 @@
|
|||||||
<div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' row')|trim})} %}{{ block('attributes') }}{% endwith %}>
|
<div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' row')|trim})} %}{{ block('attributes') }}{% endwith %}>
|
||||||
<div class="large-12 columns{% if not valid %} error{% endif %}">
|
<div class="large-12 columns{% if not valid %} error{% endif %}">
|
||||||
{{ form_widget(form) }}
|
{{ form_widget(form) }}
|
||||||
|
{{- form_help(form) -}}
|
||||||
{{ form_errors(form) }}
|
{{ form_errors(form) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -320,6 +321,7 @@
|
|||||||
<div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' row')|trim})} %}{{ block('attributes') }}{% endwith %}>
|
<div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' row')|trim})} %}{{ block('attributes') }}{% endwith %}>
|
||||||
<div class="large-12 columns{% if not valid %} error{% endif %}">
|
<div class="large-12 columns{% if not valid %} error{% endif %}">
|
||||||
{{ form_widget(form) }}
|
{{ form_widget(form) }}
|
||||||
|
{{- form_help(form) -}}
|
||||||
{{ form_errors(form) }}
|
{{ form_errors(form) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -163,4 +163,23 @@ abstract class AbstractBootstrap3HorizontalLayoutTest extends AbstractBootstrap3
|
|||||||
|
|
||||||
$this->assertMatchesXpath($html, '/div[@class="form-group"]/div[@class="col-sm-2" or @class="col-sm-10"]', 2);
|
$this->assertMatchesXpath($html, '/div[@class="form-group"]/div[@class="col-sm-2" or @class="col-sm-10"]', 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testCheckboxRowWithHelp()
|
||||||
|
{
|
||||||
|
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\CheckboxType');
|
||||||
|
$html = $this->renderRow($form->createView(), ['label' => 'foo', 'help' => 'really helpful text']);
|
||||||
|
|
||||||
|
$this->assertMatchesXpath($html,
|
||||||
|
'/div
|
||||||
|
[@class="form-group"]
|
||||||
|
[
|
||||||
|
./div[@class="col-sm-2" or @class="col-sm-10"]
|
||||||
|
/following-sibling::div[@class="col-sm-2" or @class="col-sm-10"]
|
||||||
|
[
|
||||||
|
./span[text() = "[trans]really helpful text[/trans]"]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
'
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -333,6 +333,21 @@ abstract class AbstractBootstrap3LayoutTest extends AbstractLayoutTest
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testCheckboxRowWithHelp()
|
||||||
|
{
|
||||||
|
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\CheckboxType');
|
||||||
|
$html = $this->renderRow($form->createView(), ['label' => 'foo', 'help' => 'really helpful text']);
|
||||||
|
|
||||||
|
$this->assertMatchesXpath($html,
|
||||||
|
'/div
|
||||||
|
[@class="form-group"]
|
||||||
|
[
|
||||||
|
./span[text() = "[trans]really helpful text[/trans]"]
|
||||||
|
]
|
||||||
|
'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function testSingleChoice()
|
public function testSingleChoice()
|
||||||
{
|
{
|
||||||
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', [
|
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', [
|
||||||
@ -2265,6 +2280,21 @@ abstract class AbstractBootstrap3LayoutTest extends AbstractLayoutTest
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testRadioRowWithHelp()
|
||||||
|
{
|
||||||
|
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\RadioType', false);
|
||||||
|
$html = $this->renderRow($form->createView(), ['label' => 'foo', 'help' => 'really helpful text']);
|
||||||
|
|
||||||
|
$this->assertMatchesXpath($html,
|
||||||
|
'/div
|
||||||
|
[@class="form-group"]
|
||||||
|
[
|
||||||
|
./span[text() = "[trans]really helpful text[/trans]"]
|
||||||
|
]
|
||||||
|
'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function testRange()
|
public function testRange()
|
||||||
{
|
{
|
||||||
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\RangeType', 42, ['attr' => ['min' => 5]]);
|
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\RangeType', 42, ['attr' => ['min' => 5]]);
|
||||||
|
@ -231,6 +231,25 @@ abstract class AbstractBootstrap4HorizontalLayoutTest extends AbstractBootstrap4
|
|||||||
./small[text() = "[trans]really helpful text[/trans]"]
|
./small[text() = "[trans]really helpful text[/trans]"]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRadioRowWithHelp()
|
||||||
|
{
|
||||||
|
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\RadioType', false);
|
||||||
|
$html = $this->renderRow($form->createView(), ['label' => 'foo', 'help' => 'really helpful text']);
|
||||||
|
|
||||||
|
$this->assertMatchesXpath($html,
|
||||||
|
'/div
|
||||||
|
[@class="form-group row"]
|
||||||
|
[
|
||||||
|
./div[@class="col-sm-2" or @class="col-sm-10"]
|
||||||
|
/following-sibling::div[@class="col-sm-2" or @class="col-sm-10"]
|
||||||
|
[
|
||||||
|
./small[text() = "[trans]really helpful text[/trans]"]
|
||||||
|
]
|
||||||
|
]
|
||||||
'
|
'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -422,6 +422,21 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testCheckboxRowWithHelp()
|
||||||
|
{
|
||||||
|
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\CheckboxType');
|
||||||
|
$html = $this->renderRow($form->createView(), ['label' => 'foo', 'help' => 'really helpful text']);
|
||||||
|
|
||||||
|
$this->assertMatchesXpath($html,
|
||||||
|
'/div
|
||||||
|
[@class="form-group"]
|
||||||
|
[
|
||||||
|
./small[text() = "[trans]really helpful text[/trans]"]
|
||||||
|
]
|
||||||
|
'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function testSingleChoiceExpanded()
|
public function testSingleChoiceExpanded()
|
||||||
{
|
{
|
||||||
$form = $this->factory->createNamed('name', ChoiceType::class, '&a', [
|
$form = $this->factory->createNamed('name', ChoiceType::class, '&a', [
|
||||||
@ -1027,6 +1042,21 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testRadioRowWithHelp()
|
||||||
|
{
|
||||||
|
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\RadioType', false);
|
||||||
|
$html = $this->renderRow($form->createView(), ['label' => 'foo', 'help' => 'really helpful text']);
|
||||||
|
|
||||||
|
$this->assertMatchesXpath($html,
|
||||||
|
'/div
|
||||||
|
[@class="form-group"]
|
||||||
|
[
|
||||||
|
./small[text() = "[trans]really helpful text[/trans]"]
|
||||||
|
]
|
||||||
|
'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function testButtonAttributeNameRepeatedIfTrue()
|
public function testButtonAttributeNameRepeatedIfTrue()
|
||||||
{
|
{
|
||||||
$form = $this->factory->createNamed('button', ButtonType::class, null, [
|
$form = $this->factory->createNamed('button', ButtonType::class, null, [
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2014-2019 Fabien Potencier
|
Copyright (c) 2014-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2004-2019 Fabien Potencier
|
Copyright (c) 2004-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -20,6 +20,7 @@ CHANGELOG
|
|||||||
4.4.0
|
4.4.0
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
* Added `anonymous: lazy` mode to firewalls to make them (not) start the session as late as possible
|
||||||
* Added `migrate_from` option to encoders configuration.
|
* Added `migrate_from` option to encoders configuration.
|
||||||
* Added new `argon2id` encoder, undeprecated the `bcrypt` and `argon2i` ones (using `auto` is still recommended by default.)
|
* Added new `argon2id` encoder, undeprecated the `bcrypt` and `argon2i` ones (using `auto` is still recommended by default.)
|
||||||
* Deprecated the usage of "query_string" without a "search_dn" and a "search_password" config key in Ldap factories.
|
* Deprecated the usage of "query_string" without a "search_dn" and a "search_password" config key in Ldap factories.
|
||||||
@ -28,7 +29,6 @@ CHANGELOG
|
|||||||
4.3.0
|
4.3.0
|
||||||
-----
|
-----
|
||||||
|
|
||||||
* Added `anonymous: lazy` mode to firewalls to make them (not) start the session as late as possible
|
|
||||||
* Added new encoder types: `auto` (recommended), `native` and `sodium`
|
* Added new encoder types: `auto` (recommended), `native` and `sodium`
|
||||||
* The normalization of the cookie names configured in the `logout.delete_cookies`
|
* The normalization of the cookie names configured in the `logout.delete_cookies`
|
||||||
option is deprecated and will be disabled in Symfony 5.0. This affects to cookies
|
option is deprecated and will be disabled in Symfony 5.0. This affects to cookies
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2004-2019 Fabien Potencier
|
Copyright (c) 2004-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2004-2019 Fabien Potencier
|
Copyright (c) 2004-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2004-2019 Fabien Potencier
|
Copyright (c) 2004-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2004-2019 Fabien Potencier
|
Copyright (c) 2004-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2004-2019 Fabien Potencier
|
Copyright (c) 2004-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2016-2019 Fabien Potencier
|
Copyright (c) 2016-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2004-2019 Fabien Potencier
|
Copyright (c) 2004-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -8,7 +8,7 @@ may be (YAML, XML, INI files, or for instance a database).
|
|||||||
Resources
|
Resources
|
||||||
---------
|
---------
|
||||||
|
|
||||||
* [Documentation](https://symfony.com/doc/current/components/config/index.html)
|
* [Documentation](https://symfony.com/doc/current/components/config.html)
|
||||||
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
||||||
* [Report issues](https://github.com/symfony/symfony/issues) and
|
* [Report issues](https://github.com/symfony/symfony/issues) and
|
||||||
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
||||||
|
@ -48,12 +48,12 @@ class FormatterHelper extends Helper
|
|||||||
foreach ($messages as $message) {
|
foreach ($messages as $message) {
|
||||||
$message = OutputFormatter::escape($message);
|
$message = OutputFormatter::escape($message);
|
||||||
$lines[] = sprintf($large ? ' %s ' : ' %s ', $message);
|
$lines[] = sprintf($large ? ' %s ' : ' %s ', $message);
|
||||||
$len = max($this->strlen($message) + ($large ? 4 : 2), $len);
|
$len = max(self::strlen($message) + ($large ? 4 : 2), $len);
|
||||||
}
|
}
|
||||||
|
|
||||||
$messages = $large ? [str_repeat(' ', $len)] : [];
|
$messages = $large ? [str_repeat(' ', $len)] : [];
|
||||||
for ($i = 0; isset($lines[$i]); ++$i) {
|
for ($i = 0; isset($lines[$i]); ++$i) {
|
||||||
$messages[] = $lines[$i].str_repeat(' ', $len - $this->strlen($lines[$i]));
|
$messages[] = $lines[$i].str_repeat(' ', $len - self::strlen($lines[$i]));
|
||||||
}
|
}
|
||||||
if ($large) {
|
if ($large) {
|
||||||
$messages[] = str_repeat(' ', $len);
|
$messages[] = str_repeat(' ', $len);
|
||||||
@ -73,17 +73,13 @@ class FormatterHelper extends Helper
|
|||||||
*/
|
*/
|
||||||
public function truncate(string $message, int $length, string $suffix = '...')
|
public function truncate(string $message, int $length, string $suffix = '...')
|
||||||
{
|
{
|
||||||
$computedLength = $length - $this->strlen($suffix);
|
$computedLength = $length - self::strlen($suffix);
|
||||||
|
|
||||||
if ($computedLength > $this->strlen($message)) {
|
if ($computedLength > self::strlen($message)) {
|
||||||
return $message;
|
return $message;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (false === $encoding = mb_detect_encoding($message, null, true)) {
|
return self::substr($message, 0, $length).$suffix;
|
||||||
return substr($message, 0, $length).$suffix;
|
|
||||||
}
|
|
||||||
|
|
||||||
return mb_substr($message, 0, $length, $encoding).$suffix;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2004-2019 Fabien Potencier
|
Copyright (c) 2004-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -7,7 +7,7 @@ interfaces.
|
|||||||
Resources
|
Resources
|
||||||
---------
|
---------
|
||||||
|
|
||||||
* [Documentation](https://symfony.com/doc/current/components/console/index.html)
|
* [Documentation](https://symfony.com/doc/current/components/console.html)
|
||||||
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
||||||
* [Report issues](https://github.com/symfony/symfony/issues) and
|
* [Report issues](https://github.com/symfony/symfony/issues) and
|
||||||
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2004-2019 Fabien Potencier
|
Copyright (c) 2004-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2004-2019 Fabien Potencier
|
Copyright (c) 2004-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -7,7 +7,7 @@ way objects are constructed in your application.
|
|||||||
Resources
|
Resources
|
||||||
---------
|
---------
|
||||||
|
|
||||||
* [Documentation](https://symfony.com/doc/current/components/dependency_injection/index.html)
|
* [Documentation](https://symfony.com/doc/current/components/dependency_injection.html)
|
||||||
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
||||||
* [Report issues](https://github.com/symfony/symfony/issues) and
|
* [Report issues](https://github.com/symfony/symfony/issues) and
|
||||||
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2004-2019 Fabien Potencier
|
Copyright (c) 2004-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2016-2019 Fabien Potencier
|
Copyright (c) 2016-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2019 Fabien Potencier
|
Copyright (c) 2019-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2004-2019 Fabien Potencier
|
Copyright (c) 2004-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -8,7 +8,7 @@ them.
|
|||||||
Resources
|
Resources
|
||||||
---------
|
---------
|
||||||
|
|
||||||
* [Documentation](https://symfony.com/doc/current/components/event_dispatcher/index.html)
|
* [Documentation](https://symfony.com/doc/current/components/event_dispatcher.html)
|
||||||
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
||||||
* [Report issues](https://github.com/symfony/symfony/issues) and
|
* [Report issues](https://github.com/symfony/symfony/issues) and
|
||||||
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2004-2019 Fabien Potencier
|
Copyright (c) 2004-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2004-2019 Fabien Potencier
|
Copyright (c) 2004-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -6,7 +6,7 @@ The Filesystem component provides basic utilities for the filesystem.
|
|||||||
Resources
|
Resources
|
||||||
---------
|
---------
|
||||||
|
|
||||||
* [Documentation](https://symfony.com/doc/current/components/filesystem/index.html)
|
* [Documentation](https://symfony.com/doc/current/components/filesystem.html)
|
||||||
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
||||||
* [Report issues](https://github.com/symfony/symfony/issues) and
|
* [Report issues](https://github.com/symfony/symfony/issues) and
|
||||||
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2004-2019 Fabien Potencier
|
Copyright (c) 2004-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2004-2019 Fabien Potencier
|
Copyright (c) 2004-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -6,7 +6,7 @@ The Form component allows you to easily create, process and reuse HTML forms.
|
|||||||
Resources
|
Resources
|
||||||
---------
|
---------
|
||||||
|
|
||||||
* [Documentation](https://symfony.com/doc/current/components/form/index.html)
|
* [Documentation](https://symfony.com/doc/current/components/form.html)
|
||||||
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
||||||
* [Report issues](https://github.com/symfony/symfony/issues) and
|
* [Report issues](https://github.com/symfony/symfony/issues) and
|
||||||
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
||||||
|
@ -135,7 +135,10 @@ class FormValidatorTest extends ConstraintValidatorTestCase
|
|||||||
$parent->add($form);
|
$parent->add($form);
|
||||||
|
|
||||||
$form->setData($object);
|
$form->setData($object);
|
||||||
|
$parent->submit([]);
|
||||||
|
|
||||||
|
$this->assertTrue($form->isSubmitted());
|
||||||
|
$this->assertTrue($form->isSynchronized());
|
||||||
$this->expectNoValidate();
|
$this->expectNoValidate();
|
||||||
|
|
||||||
$this->validator->validate($form, new Form());
|
$this->validator->validate($form, new Form());
|
||||||
@ -190,10 +193,15 @@ class FormValidatorTest extends ConstraintValidatorTestCase
|
|||||||
'validation_groups' => [],
|
'validation_groups' => [],
|
||||||
])
|
])
|
||||||
->setData($object)
|
->setData($object)
|
||||||
|
->setCompound(true)
|
||||||
|
->setDataMapper(new PropertyPathMapper())
|
||||||
->getForm();
|
->getForm();
|
||||||
|
|
||||||
$form->setData($object);
|
$form->setData($object);
|
||||||
|
$form->submit([]);
|
||||||
|
|
||||||
|
$this->assertTrue($form->isSubmitted());
|
||||||
|
$this->assertTrue($form->isSynchronized());
|
||||||
$this->expectNoValidate();
|
$this->expectNoValidate();
|
||||||
|
|
||||||
$this->validator->validate($form, new Form());
|
$this->validator->validate($form, new Form());
|
||||||
@ -216,6 +224,8 @@ class FormValidatorTest extends ConstraintValidatorTestCase
|
|||||||
// Launch transformer
|
// Launch transformer
|
||||||
$form->submit('foo');
|
$form->submit('foo');
|
||||||
|
|
||||||
|
$this->assertTrue($form->isSubmitted());
|
||||||
|
$this->assertTrue($form->isSynchronized());
|
||||||
$this->expectNoValidate();
|
$this->expectNoValidate();
|
||||||
|
|
||||||
$this->validator->validate($form, new Form());
|
$this->validator->validate($form, new Form());
|
||||||
@ -238,6 +248,8 @@ class FormValidatorTest extends ConstraintValidatorTestCase
|
|||||||
$form->add($child);
|
$form->add($child);
|
||||||
$form->submit([]);
|
$form->submit([]);
|
||||||
|
|
||||||
|
$this->assertTrue($form->isSubmitted());
|
||||||
|
$this->assertTrue($form->isSynchronized());
|
||||||
$this->expectNoValidate();
|
$this->expectNoValidate();
|
||||||
|
|
||||||
$this->validator->validate($form, new Form());
|
$this->validator->validate($form, new Form());
|
||||||
@ -266,6 +278,8 @@ class FormValidatorTest extends ConstraintValidatorTestCase
|
|||||||
// Launch transformer
|
// Launch transformer
|
||||||
$form->submit('foo');
|
$form->submit('foo');
|
||||||
|
|
||||||
|
$this->assertTrue($form->isSubmitted());
|
||||||
|
$this->assertFalse($form->isSynchronized());
|
||||||
$this->expectNoValidate();
|
$this->expectNoValidate();
|
||||||
|
|
||||||
$this->validator->validate($form, new Form());
|
$this->validator->validate($form, new Form());
|
||||||
@ -301,6 +315,8 @@ class FormValidatorTest extends ConstraintValidatorTestCase
|
|||||||
// Launch transformer
|
// Launch transformer
|
||||||
$form->submit('foo');
|
$form->submit('foo');
|
||||||
|
|
||||||
|
$this->assertTrue($form->isSubmitted());
|
||||||
|
$this->assertFalse($form->isSynchronized());
|
||||||
$this->expectNoValidate();
|
$this->expectNoValidate();
|
||||||
|
|
||||||
$this->validator->validate($form, new Form());
|
$this->validator->validate($form, new Form());
|
||||||
@ -412,6 +428,8 @@ class FormValidatorTest extends ConstraintValidatorTestCase
|
|||||||
// Launch transformer
|
// Launch transformer
|
||||||
$form->submit(['child' => 'foo']);
|
$form->submit(['child' => 'foo']);
|
||||||
|
|
||||||
|
$this->assertTrue($form->isSubmitted());
|
||||||
|
$this->assertFalse($form->isSynchronized());
|
||||||
$this->expectNoValidate();
|
$this->expectNoValidate();
|
||||||
|
|
||||||
$this->validator->validate($form, new Form());
|
$this->validator->validate($form, new Form());
|
||||||
@ -617,7 +635,10 @@ class FormValidatorTest extends ConstraintValidatorTestCase
|
|||||||
$form = $this->getBuilder()
|
$form = $this->getBuilder()
|
||||||
->setData('scalar')
|
->setData('scalar')
|
||||||
->getForm();
|
->getForm();
|
||||||
|
$form->submit('foo');
|
||||||
|
|
||||||
|
$this->assertTrue($form->isSubmitted());
|
||||||
|
$this->assertTrue($form->isSynchronized());
|
||||||
$this->expectNoValidate();
|
$this->expectNoValidate();
|
||||||
|
|
||||||
$this->validator->validate($form, new Form());
|
$this->validator->validate($form, new Form());
|
||||||
@ -635,6 +656,8 @@ class FormValidatorTest extends ConstraintValidatorTestCase
|
|||||||
|
|
||||||
$form->submit(['foo' => 'bar']);
|
$form->submit(['foo' => 'bar']);
|
||||||
|
|
||||||
|
$this->assertTrue($form->isSubmitted());
|
||||||
|
$this->assertTrue($form->isSynchronized());
|
||||||
$this->expectNoValidate();
|
$this->expectNoValidate();
|
||||||
|
|
||||||
$this->validator->validate($form, new Form());
|
$this->validator->validate($form, new Form());
|
||||||
@ -656,6 +679,8 @@ class FormValidatorTest extends ConstraintValidatorTestCase
|
|||||||
|
|
||||||
$form->submit(['foo' => 'bar', 'baz' => 'qux', 'quux' => 'quuz']);
|
$form->submit(['foo' => 'bar', 'baz' => 'qux', 'quux' => 'quuz']);
|
||||||
|
|
||||||
|
$this->assertTrue($form->isSubmitted());
|
||||||
|
$this->assertTrue($form->isSynchronized());
|
||||||
$this->expectNoValidate();
|
$this->expectNoValidate();
|
||||||
|
|
||||||
$this->validator->validate($form, new Form());
|
$this->validator->validate($form, new Form());
|
||||||
|
@ -288,7 +288,7 @@ final class CurlHttpClient implements HttpClientInterface, LoggerAwareInterface,
|
|||||||
$pushedResponse = $pushedResponse->response;
|
$pushedResponse = $pushedResponse->response;
|
||||||
$pushedResponse->__construct($this->multi, $url, $options, $this->logger);
|
$pushedResponse->__construct($this->multi, $url, $options, $this->logger);
|
||||||
} else {
|
} else {
|
||||||
$this->logger && $this->logger->debug(sprintf('Rejecting pushed response: "%s".', $url));
|
$this->logger && $this->logger->debug(sprintf('Rejecting pushed response: "%s"', $url));
|
||||||
$pushedResponse = null;
|
$pushedResponse = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -412,7 +412,7 @@ final class CurlHttpClient implements HttpClientInterface, LoggerAwareInterface,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (['proxy', 'no_proxy', 'bindto'] as $k) {
|
foreach (['proxy', 'no_proxy', 'bindto', 'local_cert', 'local_pk'] as $k) {
|
||||||
if ($options[$k] !== $pushedResponse->parentOptions[$k]) {
|
if ($options[$k] !== $pushedResponse->parentOptions[$k]) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2018-2019 Fabien Potencier
|
Copyright (c) 2018-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -169,7 +169,7 @@ final class NativeHttpClient implements HttpClientInterface, LoggerAwareInterfac
|
|||||||
$this->multi->dnsCache = $options['resolve'] + $this->multi->dnsCache;
|
$this->multi->dnsCache = $options['resolve'] + $this->multi->dnsCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->logger && $this->logger->info(sprintf('Request: %s %s', $method, implode('', $url)));
|
$this->logger && $this->logger->info(sprintf('Request: "%s %s"', $method, implode('', $url)));
|
||||||
|
|
||||||
[$host, $port, $url['authority']] = self::dnsResolve($url, $this->multi, $info, $onProgress);
|
[$host, $port, $url['authority']] = self::dnsResolve($url, $this->multi, $info, $onProgress);
|
||||||
|
|
||||||
@ -187,7 +187,7 @@ final class NativeHttpClient implements HttpClientInterface, LoggerAwareInterfac
|
|||||||
|
|
||||||
$context = [
|
$context = [
|
||||||
'http' => [
|
'http' => [
|
||||||
'protocol_version' => $options['http_version'] ?: '1.1',
|
'protocol_version' => min($options['http_version'] ?: '1.1', '1.1'),
|
||||||
'method' => $method,
|
'method' => $method,
|
||||||
'content' => $options['body'],
|
'content' => $options['body'],
|
||||||
'ignore_errors' => true,
|
'ignore_errors' => true,
|
||||||
@ -357,7 +357,7 @@ final class NativeHttpClient implements HttpClientInterface, LoggerAwareInterfac
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (isset($options['normalized_headers']['authorization']) || isset($options['normalized_headers']['cookie'])) {
|
if (isset($options['normalized_headers']['authorization']) || isset($options['normalized_headers']['cookie'])) {
|
||||||
$redirectHeaders['no_auth'] = array_filter($options['headers'], static function ($h) {
|
$redirectHeaders['no_auth'] = array_filter($redirectHeaders['no_auth'], static function ($h) {
|
||||||
return 0 !== stripos($h, 'Authorization:') && 0 !== stripos($h, 'Cookie:');
|
return 0 !== stripos($h, 'Authorization:') && 0 !== stripos($h, 'Cookie:');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -162,13 +162,13 @@ final class NativeResponse implements ResponseInterface
|
|||||||
restore_error_handler();
|
restore_error_handler();
|
||||||
}
|
}
|
||||||
|
|
||||||
stream_set_blocking($h, false);
|
if (isset($context['ssl']['capture_peer_cert_chain']) && isset(($context = stream_context_get_options($this->context))['ssl']['peer_certificate_chain'])) {
|
||||||
$this->context = $this->resolveRedirect = null;
|
|
||||||
|
|
||||||
if (isset($context['ssl']['peer_certificate_chain'])) {
|
|
||||||
$this->info['peer_certificate_chain'] = $context['ssl']['peer_certificate_chain'];
|
$this->info['peer_certificate_chain'] = $context['ssl']['peer_certificate_chain'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stream_set_blocking($h, false);
|
||||||
|
$this->context = $this->resolveRedirect = null;
|
||||||
|
|
||||||
// Create dechunk and inflate buffers
|
// Create dechunk and inflate buffers
|
||||||
if (isset($this->headers['content-length'])) {
|
if (isset($this->headers['content-length'])) {
|
||||||
$this->remaining = (int) $this->headers['content-length'][0];
|
$this->remaining = (int) $this->headers['content-length'][0];
|
||||||
|
@ -204,7 +204,11 @@ trait ResponseTrait
|
|||||||
$this->getHeaders($throw);
|
$this->getHeaders($throw);
|
||||||
}
|
}
|
||||||
|
|
||||||
return StreamWrapper::createResource($this, null, $this->content, $this->handle && 'stream' === get_resource_type($this->handle) ? $this->handle : null);
|
$stream = StreamWrapper::createResource($this);
|
||||||
|
stream_get_meta_data($stream)['wrapper_data']
|
||||||
|
->bindHandles($this->handle, $this->content);
|
||||||
|
|
||||||
|
return $stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,19 +37,17 @@ class StreamWrapper
|
|||||||
/** @var resource|null */
|
/** @var resource|null */
|
||||||
private $handle;
|
private $handle;
|
||||||
|
|
||||||
|
private $blocking = true;
|
||||||
|
private $timeout;
|
||||||
private $eof = false;
|
private $eof = false;
|
||||||
private $offset = 0;
|
private $offset = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a PHP stream resource from a ResponseInterface.
|
* Creates a PHP stream resource from a ResponseInterface.
|
||||||
*
|
*
|
||||||
* @param resource|null $contentBuffer The seekable resource where the response body is buffered
|
|
||||||
* @param resource|null $selectHandle The resource handle that should be monitored when
|
|
||||||
* stream_select() is used on the created stream
|
|
||||||
*
|
|
||||||
* @return resource
|
* @return resource
|
||||||
*/
|
*/
|
||||||
public static function createResource(ResponseInterface $response, HttpClientInterface $client = null, $contentBuffer = null, $selectHandle = null)
|
public static function createResource(ResponseInterface $response, HttpClientInterface $client = null)
|
||||||
{
|
{
|
||||||
if (null === $client && !method_exists($response, 'stream')) {
|
if (null === $client && !method_exists($response, 'stream')) {
|
||||||
throw new \InvalidArgumentException(sprintf('Providing a client to "%s()" is required when the response doesn\'t have any "stream()" method.', __CLASS__));
|
throw new \InvalidArgumentException(sprintf('Providing a client to "%s()" is required when the response doesn\'t have any "stream()" method.', __CLASS__));
|
||||||
@ -63,8 +61,6 @@ class StreamWrapper
|
|||||||
$context = [
|
$context = [
|
||||||
'client' => $client ?? $response,
|
'client' => $client ?? $response,
|
||||||
'response' => $response,
|
'response' => $response,
|
||||||
'content' => $contentBuffer,
|
|
||||||
'handle' => $selectHandle,
|
|
||||||
];
|
];
|
||||||
|
|
||||||
return fopen('symfony://'.$response->getInfo('url'), 'r', false, stream_context_create(['symfony' => $context])) ?: null;
|
return fopen('symfony://'.$response->getInfo('url'), 'r', false, stream_context_create(['symfony' => $context])) ?: null;
|
||||||
@ -78,6 +74,17 @@ class StreamWrapper
|
|||||||
return $this->response;
|
return $this->response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param resource|null $handle The resource handle that should be monitored when
|
||||||
|
* stream_select() is used on the created stream
|
||||||
|
* @param resource|null $content The seekable resource where the response body is buffered
|
||||||
|
*/
|
||||||
|
public function bindHandles(&$handle, &$content): void
|
||||||
|
{
|
||||||
|
$this->handle = &$handle;
|
||||||
|
$this->content = &$content;
|
||||||
|
}
|
||||||
|
|
||||||
public function stream_open(string $path, string $mode, int $options): bool
|
public function stream_open(string $path, string $mode, int $options): bool
|
||||||
{
|
{
|
||||||
if ('r' !== $mode) {
|
if ('r' !== $mode) {
|
||||||
@ -91,8 +98,6 @@ class StreamWrapper
|
|||||||
$context = stream_context_get_options($this->context)['symfony'] ?? null;
|
$context = stream_context_get_options($this->context)['symfony'] ?? null;
|
||||||
$this->client = $context['client'] ?? null;
|
$this->client = $context['client'] ?? null;
|
||||||
$this->response = $context['response'] ?? null;
|
$this->response = $context['response'] ?? null;
|
||||||
$this->content = $context['content'] ?? null;
|
|
||||||
$this->handle = $context['handle'] ?? null;
|
|
||||||
$this->context = null;
|
$this->context = null;
|
||||||
|
|
||||||
if (null !== $this->client && null !== $this->response) {
|
if (null !== $this->client && null !== $this->response) {
|
||||||
@ -147,7 +152,7 @@ class StreamWrapper
|
|||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($this->client->stream([$this->response]) as $chunk) {
|
foreach ($this->client->stream([$this->response], $this->blocking ? $this->timeout : 0) as $chunk) {
|
||||||
try {
|
try {
|
||||||
$this->eof = true;
|
$this->eof = true;
|
||||||
$this->eof = !$chunk->isTimeout();
|
$this->eof = !$chunk->isTimeout();
|
||||||
@ -178,6 +183,19 @@ class StreamWrapper
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function stream_set_option(int $option, int $arg1, ?int $arg2): bool
|
||||||
|
{
|
||||||
|
if (STREAM_OPTION_BLOCKING === $option) {
|
||||||
|
$this->blocking = (bool) $arg1;
|
||||||
|
} elseif (STREAM_OPTION_READ_TIMEOUT === $option) {
|
||||||
|
$this->timeout = $arg1 + $arg2 / 1e6;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public function stream_tell(): int
|
public function stream_tell(): int
|
||||||
{
|
{
|
||||||
return $this->offset;
|
return $this->offset;
|
||||||
@ -238,6 +256,8 @@ class StreamWrapper
|
|||||||
public function stream_cast(int $castAs)
|
public function stream_cast(int $castAs)
|
||||||
{
|
{
|
||||||
if (STREAM_CAST_FOR_SELECT === $castAs) {
|
if (STREAM_CAST_FOR_SELECT === $castAs) {
|
||||||
|
$this->response->getHeaders(false);
|
||||||
|
|
||||||
return $this->handle ?? false;
|
return $this->handle ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,4 +75,20 @@ abstract class HttpClientTestCase extends BaseHttpClientTestCase
|
|||||||
$response = $client->request('GET', 'http://localhost:8057/404');
|
$response = $client->request('GET', 'http://localhost:8057/404');
|
||||||
$stream = $response->toStream();
|
$stream = $response->toStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testNonBlockingStream()
|
||||||
|
{
|
||||||
|
$client = $this->getHttpClient(__FUNCTION__);
|
||||||
|
$response = $client->request('GET', 'http://localhost:8057/timeout-body');
|
||||||
|
$stream = $response->toStream();
|
||||||
|
|
||||||
|
$this->assertTrue(stream_set_blocking($stream, false));
|
||||||
|
$this->assertSame('<1>', fread($stream, 8192));
|
||||||
|
$this->assertFalse(feof($stream));
|
||||||
|
|
||||||
|
$this->assertTrue(stream_set_blocking($stream, true));
|
||||||
|
$this->assertSame('<2>', fread($stream, 8192));
|
||||||
|
$this->assertSame('', fread($stream, 8192));
|
||||||
|
$this->assertTrue(feof($stream));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -171,6 +171,10 @@ class MockHttpClientTest extends HttpClientTestCase
|
|||||||
|
|
||||||
return $client;
|
return $client;
|
||||||
|
|
||||||
|
case 'testNonBlockingStream':
|
||||||
|
$responses[] = new MockResponse((function () { yield '<1>'; yield ''; yield '<2>'; })(), ['response_headers' => $headers]);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'testMaxDuration':
|
case 'testMaxDuration':
|
||||||
$mock = $this->getMockBuilder(ResponseInterface::class)->getMock();
|
$mock = $this->getMockBuilder(ResponseInterface::class)->getMock();
|
||||||
$mock->expects($this->any())
|
$mock->expects($this->any())
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2004-2019 Fabien Potencier
|
Copyright (c) 2004-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -7,7 +7,7 @@ specification.
|
|||||||
Resources
|
Resources
|
||||||
---------
|
---------
|
||||||
|
|
||||||
* [Documentation](https://symfony.com/doc/current/components/http_foundation/index.html)
|
* [Documentation](https://symfony.com/doc/current/components/http_foundation.html)
|
||||||
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
||||||
* [Report issues](https://github.com/symfony/symfony/issues) and
|
* [Report issues](https://github.com/symfony/symfony/issues) and
|
||||||
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2004-2019 Fabien Potencier
|
Copyright (c) 2004-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -9,7 +9,7 @@ an advanced CMS system (Drupal).
|
|||||||
Resources
|
Resources
|
||||||
---------
|
---------
|
||||||
|
|
||||||
* [Documentation](https://symfony.com/doc/current/components/http_kernel/index.html)
|
* [Documentation](https://symfony.com/doc/current/components/http_kernel.html)
|
||||||
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
||||||
* [Report issues](https://github.com/symfony/symfony/issues) and
|
* [Report issues](https://github.com/symfony/symfony/issues) and
|
||||||
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2012-2019 Fabien Potencier
|
Copyright (c) 2012-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2004-2019 Fabien Potencier
|
Copyright (c) 2004-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2004-2019 Fabien Potencier
|
Copyright (c) 2004-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2016-2019 Fabien Potencier
|
Copyright (c) 2016-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2019 Fabien Potencier
|
Copyright (c) 2019-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2019 Fabien Potencier
|
Copyright (c) 2019-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2019 Fabien Potencier
|
Copyright (c) 2019-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -13,6 +13,9 @@ namespace Symfony\Component\Mailer\Bridge\Mailchimp\Tests\Transport;
|
|||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Symfony\Component\Mailer\Bridge\Mailchimp\Transport\MandrillApiTransport;
|
use Symfony\Component\Mailer\Bridge\Mailchimp\Transport\MandrillApiTransport;
|
||||||
|
use Symfony\Component\Mailer\Envelope;
|
||||||
|
use Symfony\Component\Mime\Address;
|
||||||
|
use Symfony\Component\Mime\Email;
|
||||||
|
|
||||||
class MandrillApiTransportTest extends TestCase
|
class MandrillApiTransportTest extends TestCase
|
||||||
{
|
{
|
||||||
@ -41,4 +44,21 @@ class MandrillApiTransportTest extends TestCase
|
|||||||
],
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testCustomHeader()
|
||||||
|
{
|
||||||
|
$email = new Email();
|
||||||
|
$email->getHeaders()->addTextHeader('foo', 'bar');
|
||||||
|
$envelope = new Envelope(new Address('alice@system.com'), [new Address('bob@system.com')]);
|
||||||
|
|
||||||
|
$transport = new MandrillApiTransport('ACCESS_KEY');
|
||||||
|
$method = new \ReflectionMethod(MandrillApiTransport::class, 'getPayload');
|
||||||
|
$method->setAccessible(true);
|
||||||
|
$payload = $method->invoke($transport, $email, $envelope);
|
||||||
|
|
||||||
|
$this->assertArrayHasKey('message', $payload);
|
||||||
|
$this->assertArrayHasKey('headers', $payload['message']);
|
||||||
|
$this->assertCount(1, $payload['message']['headers']);
|
||||||
|
$this->assertEquals('foo: bar', $payload['message']['headers'][0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -94,10 +94,14 @@ class MandrillApiTransport extends AbstractApiTransport
|
|||||||
'type' => $headers->get('Content-Type')->getBody(),
|
'type' => $headers->get('Content-Type')->getBody(),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if ($name = $headers->getHeaderParameter('Content-Disposition', 'name')) {
|
||||||
|
$att['name'] = $name;
|
||||||
|
}
|
||||||
|
|
||||||
if ('inline' === $disposition) {
|
if ('inline' === $disposition) {
|
||||||
$payload['images'][] = $att;
|
$payload['message']['images'][] = $att;
|
||||||
} else {
|
} else {
|
||||||
$payload['attachments'][] = $att;
|
$payload['message']['attachments'][] = $att;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +111,7 @@ class MandrillApiTransport extends AbstractApiTransport
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$payload['message']['headers'][] = $name.': '.$header->toString();
|
$payload['message']['headers'][] = $name.': '.$header->getBodyAsString();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $payload;
|
return $payload;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2019 Fabien Potencier
|
Copyright (c) 2019-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -13,6 +13,9 @@ namespace Symfony\Component\Mailer\Bridge\Mailgun\Tests\Transport;
|
|||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Symfony\Component\Mailer\Bridge\Mailgun\Transport\MailgunApiTransport;
|
use Symfony\Component\Mailer\Bridge\Mailgun\Transport\MailgunApiTransport;
|
||||||
|
use Symfony\Component\Mailer\Envelope;
|
||||||
|
use Symfony\Component\Mime\Address;
|
||||||
|
use Symfony\Component\Mime\Email;
|
||||||
|
|
||||||
class MailgunApiTransportTest extends TestCase
|
class MailgunApiTransportTest extends TestCase
|
||||||
{
|
{
|
||||||
@ -45,4 +48,20 @@ class MailgunApiTransportTest extends TestCase
|
|||||||
],
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testCustomHeader()
|
||||||
|
{
|
||||||
|
$json = json_encode(['foo' => 'bar']);
|
||||||
|
$email = new Email();
|
||||||
|
$email->getHeaders()->addTextHeader('X-Mailgun-Variables', $json);
|
||||||
|
$envelope = new Envelope(new Address('alice@system.com'), [new Address('bob@system.com')]);
|
||||||
|
|
||||||
|
$transport = new MailgunApiTransport('ACCESS_KEY', 'DOMAIN');
|
||||||
|
$method = new \ReflectionMethod(MailgunApiTransport::class, 'getPayload');
|
||||||
|
$method->setAccessible(true);
|
||||||
|
$payload = $method->invoke($transport, $email, $envelope);
|
||||||
|
|
||||||
|
$this->assertArrayHasKey('h:x-mailgun-variables', $payload);
|
||||||
|
$this->assertEquals($json, $payload['h:x-mailgun-variables']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,7 +114,7 @@ class MailgunApiTransport extends AbstractApiTransport
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$payload['h:'.$name] = $header->toString();
|
$payload['h:'.$name] = $header->getBodyAsString();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $payload;
|
return $payload;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2019 Fabien Potencier
|
Copyright (c) 2019-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -13,6 +13,9 @@ namespace Symfony\Component\Mailer\Bridge\Postmark\Tests\Transport;
|
|||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkApiTransport;
|
use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkApiTransport;
|
||||||
|
use Symfony\Component\Mailer\Envelope;
|
||||||
|
use Symfony\Component\Mime\Address;
|
||||||
|
use Symfony\Component\Mime\Email;
|
||||||
|
|
||||||
class PostmarkApiTransportTest extends TestCase
|
class PostmarkApiTransportTest extends TestCase
|
||||||
{
|
{
|
||||||
@ -41,4 +44,21 @@ class PostmarkApiTransportTest extends TestCase
|
|||||||
],
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testCustomHeader()
|
||||||
|
{
|
||||||
|
$email = new Email();
|
||||||
|
$email->getHeaders()->addTextHeader('foo', 'bar');
|
||||||
|
$envelope = new Envelope(new Address('alice@system.com'), [new Address('bob@system.com')]);
|
||||||
|
|
||||||
|
$transport = new PostmarkApiTransport('ACCESS_KEY');
|
||||||
|
$method = new \ReflectionMethod(PostmarkApiTransport::class, 'getPayload');
|
||||||
|
$method->setAccessible(true);
|
||||||
|
$payload = $method->invoke($transport, $email, $envelope);
|
||||||
|
|
||||||
|
$this->assertArrayHasKey('Headers', $payload);
|
||||||
|
$this->assertCount(1, $payload['Headers']);
|
||||||
|
|
||||||
|
$this->assertEquals(['Name' => 'foo', 'Value' => 'bar'], $payload['Headers'][0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ class PostmarkApiTransport extends AbstractApiTransport
|
|||||||
|
|
||||||
$payload['Headers'][] = [
|
$payload['Headers'][] = [
|
||||||
'Name' => $name,
|
'Name' => $name,
|
||||||
'Value' => $header->toString(),
|
'Value' => $header->getBodyAsString(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2019 Fabien Potencier
|
Copyright (c) 2019-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -13,6 +13,8 @@ namespace Symfony\Component\Mailer\Bridge\Sendgrid\Tests\Transport;
|
|||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridApiTransport;
|
use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridApiTransport;
|
||||||
|
use Symfony\Component\Mailer\Envelope;
|
||||||
|
use Symfony\Component\Mime\Address;
|
||||||
use Symfony\Component\Mime\Email;
|
use Symfony\Component\Mime\Email;
|
||||||
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||||
use Symfony\Contracts\HttpClient\ResponseInterface;
|
use Symfony\Contracts\HttpClient\ResponseInterface;
|
||||||
@ -48,8 +50,8 @@ class SendgridApiTransportTest extends TestCase
|
|||||||
public function testSend()
|
public function testSend()
|
||||||
{
|
{
|
||||||
$email = new Email();
|
$email = new Email();
|
||||||
$email->from('foo@example.com')
|
$email->from(new Address('foo@example.com', 'Ms. Foo Bar'))
|
||||||
->to('bar@example.com')
|
->to(new Address('bar@example.com', 'Mr. Recipient'))
|
||||||
->bcc('baz@example.com')
|
->bcc('baz@example.com')
|
||||||
->text('content');
|
->text('content');
|
||||||
|
|
||||||
@ -73,12 +75,18 @@ class SendgridApiTransportTest extends TestCase
|
|||||||
'json' => [
|
'json' => [
|
||||||
'personalizations' => [
|
'personalizations' => [
|
||||||
[
|
[
|
||||||
'to' => [['email' => 'bar@example.com']],
|
'to' => [[
|
||||||
|
'email' => 'bar@example.com',
|
||||||
|
'name' => 'Mr. Recipient',
|
||||||
|
]],
|
||||||
'subject' => null,
|
'subject' => null,
|
||||||
'bcc' => [['email' => 'baz@example.com']],
|
'bcc' => [['email' => 'baz@example.com']],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
'from' => ['email' => 'foo@example.com'],
|
'from' => [
|
||||||
|
'email' => 'foo@example.com',
|
||||||
|
'name' => 'Ms. Foo Bar',
|
||||||
|
],
|
||||||
'content' => [
|
'content' => [
|
||||||
['type' => 'text/plain', 'value' => 'content'],
|
['type' => 'text/plain', 'value' => 'content'],
|
||||||
],
|
],
|
||||||
@ -90,4 +98,72 @@ class SendgridApiTransportTest extends TestCase
|
|||||||
$mailer = new SendgridApiTransport('foo', $httpClient);
|
$mailer = new SendgridApiTransport('foo', $httpClient);
|
||||||
$mailer->send($email);
|
$mailer->send($email);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testLineBreaksInEncodedAttachment()
|
||||||
|
{
|
||||||
|
$email = new Email();
|
||||||
|
$email->from('foo@example.com')
|
||||||
|
->to('bar@example.com')
|
||||||
|
// even if content doesn't include new lines, the base64 encoding performed later may add them
|
||||||
|
->attach('Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod', 'lorem.txt');
|
||||||
|
|
||||||
|
$response = $this->createMock(ResponseInterface::class);
|
||||||
|
|
||||||
|
$response
|
||||||
|
->expects($this->once())
|
||||||
|
->method('getStatusCode')
|
||||||
|
->willReturn(202);
|
||||||
|
$response
|
||||||
|
->expects($this->once())
|
||||||
|
->method('getHeaders')
|
||||||
|
->willReturn(['x-message-id' => '1']);
|
||||||
|
|
||||||
|
$httpClient = $this->createMock(HttpClientInterface::class);
|
||||||
|
|
||||||
|
$httpClient
|
||||||
|
->expects($this->once())
|
||||||
|
->method('request')
|
||||||
|
->with('POST', 'https://api.sendgrid.com/v3/mail/send', [
|
||||||
|
'json' => [
|
||||||
|
'personalizations' => [
|
||||||
|
[
|
||||||
|
'to' => [['email' => 'bar@example.com']],
|
||||||
|
'subject' => null,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'from' => ['email' => 'foo@example.com'],
|
||||||
|
'content' => [],
|
||||||
|
'attachments' => [
|
||||||
|
[
|
||||||
|
'content' => 'TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdCwgc2VkIGRvIGVpdXNtb2Q=',
|
||||||
|
'filename' => 'lorem.txt',
|
||||||
|
'type' => 'application/octet-stream',
|
||||||
|
'disposition' => 'attachment',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'auth_bearer' => 'foo',
|
||||||
|
])
|
||||||
|
->willReturn($response);
|
||||||
|
|
||||||
|
$mailer = new SendgridApiTransport('foo', $httpClient);
|
||||||
|
|
||||||
|
$mailer->send($email);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCustomHeader()
|
||||||
|
{
|
||||||
|
$email = new Email();
|
||||||
|
$email->getHeaders()->addTextHeader('foo', 'bar');
|
||||||
|
$envelope = new Envelope(new Address('alice@system.com'), [new Address('bob@system.com')]);
|
||||||
|
|
||||||
|
$transport = new SendgridApiTransport('ACCESS_KEY');
|
||||||
|
$method = new \ReflectionMethod(SendgridApiTransport::class, 'getPayload');
|
||||||
|
$method->setAccessible(true);
|
||||||
|
$payload = $method->invoke($transport, $email, $envelope);
|
||||||
|
|
||||||
|
$this->assertArrayHasKey('headers', $payload);
|
||||||
|
$this->assertArrayHasKey('foo', $payload['headers']);
|
||||||
|
$this->assertEquals('bar', $payload['headers']['foo']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,11 +63,19 @@ class SendgridApiTransport extends AbstractApiTransport
|
|||||||
|
|
||||||
private function getPayload(Email $email, Envelope $envelope): array
|
private function getPayload(Email $email, Envelope $envelope): array
|
||||||
{
|
{
|
||||||
$addressStringifier = function (Address $address) {return ['email' => $address->toString()]; };
|
$addressStringifier = function (Address $address) {
|
||||||
|
$stringified = ['email' => $address->getAddress()];
|
||||||
|
|
||||||
|
if ($address->getName()) {
|
||||||
|
$stringified['name'] = $address->getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $stringified;
|
||||||
|
};
|
||||||
|
|
||||||
$payload = [
|
$payload = [
|
||||||
'personalizations' => [],
|
'personalizations' => [],
|
||||||
'from' => ['email' => $envelope->getSender()->toString()],
|
'from' => $addressStringifier($envelope->getSender()),
|
||||||
'content' => $this->getContent($email),
|
'content' => $this->getContent($email),
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -96,7 +104,7 @@ class SendgridApiTransport extends AbstractApiTransport
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$payload['headers'][$name] = $header->toString();
|
$payload['headers'][$name] = $header->getBodyAsString();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $payload;
|
return $payload;
|
||||||
@ -124,7 +132,7 @@ class SendgridApiTransport extends AbstractApiTransport
|
|||||||
$disposition = $headers->getHeaderBody('Content-Disposition');
|
$disposition = $headers->getHeaderBody('Content-Disposition');
|
||||||
|
|
||||||
$att = [
|
$att = [
|
||||||
'content' => $attachment->bodyToString(),
|
'content' => str_replace("\r\n", '', $attachment->bodyToString()),
|
||||||
'type' => $headers->get('Content-Type')->getBody(),
|
'type' => $headers->get('Content-Type')->getBody(),
|
||||||
'filename' => $filename,
|
'filename' => $filename,
|
||||||
'disposition' => $disposition,
|
'disposition' => $disposition,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2019 Fabien Potencier
|
Copyright (c) 2019-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2018-2019 Fabien Potencier
|
Copyright (c) 2018-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2010-2019 Fabien Potencier
|
Copyright (c) 2010-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2004-2019 Fabien Potencier
|
Copyright (c) 2004-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2004-2019 Fabien Potencier
|
Copyright (c) 2004-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2004-2019 Fabien Potencier
|
Copyright (c) 2004-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -7,7 +7,7 @@ object or array using a simple string notation.
|
|||||||
Resources
|
Resources
|
||||||
---------
|
---------
|
||||||
|
|
||||||
* [Documentation](https://symfony.com/doc/current/components/property_access/index.html)
|
* [Documentation](https://symfony.com/doc/current/components/property_access.html)
|
||||||
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
||||||
* [Report issues](https://github.com/symfony/symfony/issues) and
|
* [Report issues](https://github.com/symfony/symfony/issues) and
|
||||||
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
||||||
|
@ -201,6 +201,8 @@ class PhpDocExtractor implements PropertyDescriptionExtractorInterface, Property
|
|||||||
return $this->docBlockFactory->create($reflectionProperty, $this->createFromReflector($reflectionProperty->getDeclaringClass()));
|
return $this->docBlockFactory->create($reflectionProperty, $this->createFromReflector($reflectionProperty->getDeclaringClass()));
|
||||||
} catch (\InvalidArgumentException $e) {
|
} catch (\InvalidArgumentException $e) {
|
||||||
return null;
|
return null;
|
||||||
|
} catch (\RuntimeException $e) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,6 +239,8 @@ class PhpDocExtractor implements PropertyDescriptionExtractorInterface, Property
|
|||||||
return [$this->docBlockFactory->create($reflectionMethod, $this->createFromReflector($reflectionMethod->getDeclaringClass())), $prefix];
|
return [$this->docBlockFactory->create($reflectionMethod, $this->createFromReflector($reflectionMethod->getDeclaringClass())), $prefix];
|
||||||
} catch (\InvalidArgumentException $e) {
|
} catch (\InvalidArgumentException $e) {
|
||||||
return null;
|
return null;
|
||||||
|
} catch (\RuntimeException $e) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2015-2019 Fabien Potencier
|
Copyright (c) 2015-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -40,7 +40,6 @@ class CompiledUrlGenerator extends UrlGenerator
|
|||||||
if (null !== $locale) {
|
if (null !== $locale) {
|
||||||
do {
|
do {
|
||||||
if (($this->compiledRoutes[$name.'.'.$locale][1]['_canonical_route'] ?? null) === $name) {
|
if (($this->compiledRoutes[$name.'.'.$locale][1]['_canonical_route'] ?? null) === $name) {
|
||||||
unset($parameters['_locale']);
|
|
||||||
$name .= '.'.$locale;
|
$name .= '.'.$locale;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -53,6 +52,14 @@ class CompiledUrlGenerator extends UrlGenerator
|
|||||||
|
|
||||||
list($variables, $defaults, $requirements, $tokens, $hostTokens, $requiredSchemes) = $this->compiledRoutes[$name];
|
list($variables, $defaults, $requirements, $tokens, $hostTokens, $requiredSchemes) = $this->compiledRoutes[$name];
|
||||||
|
|
||||||
|
if (isset($defaults['_canonical_route']) && isset($defaults['_locale'])) {
|
||||||
|
if (!\in_array('_locale', $variables, true)) {
|
||||||
|
unset($parameters['_locale']);
|
||||||
|
} elseif (!isset($parameters['_locale'])) {
|
||||||
|
$parameters['_locale'] = $defaults['_locale'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return $this->doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens, $requiredSchemes);
|
return $this->doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens, $requiredSchemes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,7 +134,6 @@ class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInt
|
|||||||
if (null !== $locale) {
|
if (null !== $locale) {
|
||||||
do {
|
do {
|
||||||
if (null !== ($route = $this->routes->get($name.'.'.$locale)) && $route->getDefault('_canonical_route') === $name) {
|
if (null !== ($route = $this->routes->get($name.'.'.$locale)) && $route->getDefault('_canonical_route') === $name) {
|
||||||
unset($parameters['_locale']);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while (false !== $locale = strstr($locale, '_', true));
|
} while (false !== $locale = strstr($locale, '_', true));
|
||||||
@ -147,7 +146,18 @@ class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInt
|
|||||||
// the Route has a cache of its own and is not recompiled as long as it does not get modified
|
// the Route has a cache of its own and is not recompiled as long as it does not get modified
|
||||||
$compiledRoute = $route->compile();
|
$compiledRoute = $route->compile();
|
||||||
|
|
||||||
return $this->doGenerate($compiledRoute->getVariables(), $route->getDefaults(), $route->getRequirements(), $compiledRoute->getTokens(), $parameters, $name, $referenceType, $compiledRoute->getHostTokens(), $route->getSchemes());
|
$defaults = $route->getDefaults();
|
||||||
|
$variables = $compiledRoute->getVariables();
|
||||||
|
|
||||||
|
if (isset($defaults['_canonical_route']) && isset($defaults['_locale'])) {
|
||||||
|
if (!\in_array('_locale', $variables, true)) {
|
||||||
|
unset($parameters['_locale']);
|
||||||
|
} elseif (!isset($parameters['_locale'])) {
|
||||||
|
$parameters['_locale'] = $defaults['_locale'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->doGenerate($variables, $defaults, $route->getRequirements(), $compiledRoute->getTokens(), $parameters, $name, $referenceType, $compiledRoute->getHostTokens(), $route->getSchemes());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2004-2019 Fabien Potencier
|
Copyright (c) 2004-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -6,7 +6,7 @@ The Routing component maps an HTTP request to a set of configuration variables.
|
|||||||
Resources
|
Resources
|
||||||
---------
|
---------
|
||||||
|
|
||||||
* [Documentation](https://symfony.com/doc/current/components/routing/index.html)
|
* [Documentation](https://symfony.com/doc/current/components/routing.html)
|
||||||
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
||||||
* [Report issues](https://github.com/symfony/symfony/issues) and
|
* [Report issues](https://github.com/symfony/symfony/issues) and
|
||||||
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
||||||
|
@ -131,9 +131,9 @@ class CompiledUrlGeneratorDumperTest extends TestCase
|
|||||||
|
|
||||||
public function testDumpWithFallbackLocaleLocalizedRoutes()
|
public function testDumpWithFallbackLocaleLocalizedRoutes()
|
||||||
{
|
{
|
||||||
$this->routeCollection->add('test.en', (new Route('/testing/is/fun'))->setDefault('_canonical_route', 'test'));
|
$this->routeCollection->add('test.en', (new Route('/testing/is/fun'))->setDefault('_locale', 'en')->setDefault('_canonical_route', 'test'));
|
||||||
$this->routeCollection->add('test.nl', (new Route('/testen/is/leuk'))->setDefault('_canonical_route', 'test'));
|
$this->routeCollection->add('test.nl', (new Route('/testen/is/leuk'))->setDefault('_locale', 'nl')->setDefault('_canonical_route', 'test'));
|
||||||
$this->routeCollection->add('test.fr', (new Route('/tester/est/amusant'))->setDefault('_canonical_route', 'test'));
|
$this->routeCollection->add('test.fr', (new Route('/tester/est/amusant'))->setDefault('_locale', 'fr')->setDefault('_canonical_route', 'test'));
|
||||||
|
|
||||||
$code = $this->generatorDumper->dump();
|
$code = $this->generatorDumper->dump();
|
||||||
file_put_contents($this->testTmpFilepath, $code);
|
file_put_contents($this->testTmpFilepath, $code);
|
||||||
@ -231,4 +231,29 @@ class CompiledUrlGeneratorDumperTest extends TestCase
|
|||||||
$this->assertEquals('https://localhost/app.php/testing', $absoluteUrl);
|
$this->assertEquals('https://localhost/app.php/testing', $absoluteUrl);
|
||||||
$this->assertEquals('/app.php/testing', $relativeUrl);
|
$this->assertEquals('/app.php/testing', $relativeUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testDumpWithLocalizedRoutesPreserveTheGoodLocaleInTheUrl()
|
||||||
|
{
|
||||||
|
$this->routeCollection->add('foo.en', (new Route('/{_locale}/foo'))->setDefault('_locale', 'en')->setDefault('_canonical_route', 'foo'));
|
||||||
|
$this->routeCollection->add('foo.fr', (new Route('/{_locale}/foo'))->setDefault('_locale', 'fr')->setDefault('_canonical_route', 'foo'));
|
||||||
|
$this->routeCollection->add('fun.en', (new Route('/fun'))->setDefault('_locale', 'en')->setDefault('_canonical_route', 'fun'));
|
||||||
|
$this->routeCollection->add('fun.fr', (new Route('/amusant'))->setDefault('_locale', 'fr')->setDefault('_canonical_route', 'fun'));
|
||||||
|
|
||||||
|
file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump());
|
||||||
|
|
||||||
|
$requestContext = new RequestContext();
|
||||||
|
$requestContext->setParameter('_locale', 'fr');
|
||||||
|
|
||||||
|
$compiledUrlGenerator = new CompiledUrlGenerator(require $this->testTmpFilepath, $requestContext, null, null);
|
||||||
|
|
||||||
|
$this->assertSame('/fr/foo', $compiledUrlGenerator->generate('foo'));
|
||||||
|
$this->assertSame('/en/foo', $compiledUrlGenerator->generate('foo.en'));
|
||||||
|
$this->assertSame('/en/foo', $compiledUrlGenerator->generate('foo', ['_locale' => 'en']));
|
||||||
|
$this->assertSame('/en/foo', $compiledUrlGenerator->generate('foo.fr', ['_locale' => 'en']));
|
||||||
|
|
||||||
|
$this->assertSame('/amusant', $compiledUrlGenerator->generate('fun'));
|
||||||
|
$this->assertSame('/fun', $compiledUrlGenerator->generate('fun.en'));
|
||||||
|
$this->assertSame('/fun', $compiledUrlGenerator->generate('fun', ['_locale' => 'en']));
|
||||||
|
$this->assertSame('/amusant', $compiledUrlGenerator->generate('fun.fr', ['_locale' => 'en']));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -236,6 +236,29 @@ class UrlGeneratorTest extends TestCase
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testDumpWithLocalizedRoutesPreserveTheGoodLocaleInTheUrl()
|
||||||
|
{
|
||||||
|
$routeCollection = new RouteCollection();
|
||||||
|
|
||||||
|
$routeCollection->add('foo.en', (new Route('/{_locale}/foo'))->setDefault('_locale', 'en')->setDefault('_canonical_route', 'foo'));
|
||||||
|
$routeCollection->add('foo.fr', (new Route('/{_locale}/foo'))->setDefault('_locale', 'fr')->setDefault('_canonical_route', 'foo'));
|
||||||
|
$routeCollection->add('fun.en', (new Route('/fun'))->setDefault('_locale', 'en')->setDefault('_canonical_route', 'fun'));
|
||||||
|
$routeCollection->add('fun.fr', (new Route('/amusant'))->setDefault('_locale', 'fr')->setDefault('_canonical_route', 'fun'));
|
||||||
|
|
||||||
|
$urlGenerator = $this->getGenerator($routeCollection);
|
||||||
|
$urlGenerator->getContext()->setParameter('_locale', 'fr');
|
||||||
|
|
||||||
|
$this->assertSame('/app.php/fr/foo', $urlGenerator->generate('foo'));
|
||||||
|
$this->assertSame('/app.php/en/foo', $urlGenerator->generate('foo.en'));
|
||||||
|
$this->assertSame('/app.php/en/foo', $urlGenerator->generate('foo', ['_locale' => 'en']));
|
||||||
|
$this->assertSame('/app.php/en/foo', $urlGenerator->generate('foo.fr', ['_locale' => 'en']));
|
||||||
|
|
||||||
|
$this->assertSame('/app.php/amusant', $urlGenerator->generate('fun'));
|
||||||
|
$this->assertSame('/app.php/fun', $urlGenerator->generate('fun.en'));
|
||||||
|
$this->assertSame('/app.php/fun', $urlGenerator->generate('fun', ['_locale' => 'en']));
|
||||||
|
$this->assertSame('/app.php/amusant', $urlGenerator->generate('fun.fr', ['_locale' => 'en']));
|
||||||
|
}
|
||||||
|
|
||||||
public function testGenerateWithoutRoutes()
|
public function testGenerateWithoutRoutes()
|
||||||
{
|
{
|
||||||
$this->expectException('Symfony\Component\Routing\Exception\RouteNotFoundException');
|
$this->expectException('Symfony\Component\Routing\Exception\RouteNotFoundException');
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2004-2019 Fabien Potencier
|
Copyright (c) 2004-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -9,7 +9,7 @@ the Java Spring framework.
|
|||||||
Resources
|
Resources
|
||||||
---------
|
---------
|
||||||
|
|
||||||
* [Documentation](https://symfony.com/doc/current/components/security/index.html)
|
* [Documentation](https://symfony.com/doc/current/components/security.html)
|
||||||
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
||||||
* [Report issues](https://github.com/symfony/symfony/issues) and
|
* [Report issues](https://github.com/symfony/symfony/issues) and
|
||||||
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2004-2019 Fabien Potencier
|
Copyright (c) 2004-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -7,7 +7,7 @@ The Security CSRF (cross-site request forgery) component provides a class
|
|||||||
Resources
|
Resources
|
||||||
---------
|
---------
|
||||||
|
|
||||||
* [Documentation](https://symfony.com/doc/current/components/security/index.html)
|
* [Documentation](https://symfony.com/doc/current/components/security.html)
|
||||||
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
||||||
* [Report issues](https://github.com/symfony/symfony/issues) and
|
* [Report issues](https://github.com/symfony/symfony/issues) and
|
||||||
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2004-2019 Fabien Potencier
|
Copyright (c) 2004-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -19,7 +19,7 @@ interface PasswordAuthenticatedInterface
|
|||||||
/**
|
/**
|
||||||
* Returns the clear-text password contained in credentials if any.
|
* Returns the clear-text password contained in credentials if any.
|
||||||
*
|
*
|
||||||
* @param mixed The user credentials
|
* @param mixed $credentials The user credentials
|
||||||
*/
|
*/
|
||||||
public function getPassword($credentials): ?string;
|
public function getPassword($credentials): ?string;
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ total control.
|
|||||||
Resources
|
Resources
|
||||||
---------
|
---------
|
||||||
|
|
||||||
* [Documentation](https://symfony.com/doc/current/components/security/index.html)
|
* [Documentation](https://symfony.com/doc/current/components/security.html)
|
||||||
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
||||||
* [Report issues](https://github.com/symfony/symfony/issues) and
|
* [Report issues](https://github.com/symfony/symfony/issues) and
|
||||||
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2004-2019 Fabien Potencier
|
Copyright (c) 2004-2020 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user