Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 15915fd

Browse files
Merge branch '3.4' into 4.0
* 3.4: (22 commits) fix merge [Translation] Fix InvalidArgumentException when using untranslated plural forms from .po files Fixed exit code with non-integer throwable code [HttpFoundation] Support 0 bit netmask in IPv6 () [DI] Impossible to set an environment variable and then an array as container parameter [Process] remove false-positive BC breaking exception on Windows Tweaking class not found autowiring error [LDAP] added missing dots at the end of some exception messages. [TwigBridge] Add missing dev requirement for workflow fixed #25440 empty lines don't count for indent detection Set `width: auto` on WebProfiler toolbar's reset. [Lock] Fix incorrect phpdoc [Process] Dont rely on putenv(), it fails on ZTS PHP [HttpKernel] detect deprecations thrown by container initialization during tests [HttpKernel] Fix logging of post-terminate errors/exceptions [DI] Add context to service-not-found exceptions thrown by service locators [Debug] Fix catching fatal errors in case of nested error handlers [VarDumper] Fixed file links leave blank pages when ide is configured Fix hidden currency element with Bootstrap 3 theme ...
2 parents 1277219 + 6aa18bf commit 15915fd

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+531
-126
lines changed

UPGRADE-4.0.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,40 @@
11
UPGRADE FROM 3.x to 4.0
22
=======================
33

4+
Symfony Framework
5+
-----------------
6+
7+
The first step to upgrade a Symfony 3.x application to 4.x is to update the
8+
file and directory structure of your application:
9+
10+
| Symfony 3.x | Symfony 4.x
11+
| ----------------------------------- | --------------------------------
12+
| `app/config/` | `config/`
13+
| `app/config/*.yml` | `config/*.yaml` and `config/packages/*.yaml`
14+
| `app/config/parameters.yml.dist` | `config/services.yaml` and `.env.dist`
15+
| `app/config/parameters.yml` | `config/services.yaml` and `.env`
16+
| `app/Resources/<BundleName>/views/` | `templates/bundles/<BundleName>/`
17+
| `app/Resources/` | `src/Resources/`
18+
| `app/Resources/assets/` | `assets/`
19+
| `app/Resources/translations/` | `translations/`
20+
| `app/Resources/views/` | `templates/`
21+
| `src/AppBundle/` | `src/`
22+
| `var/logs/` | `var/log/`
23+
| `web/` | `public/`
24+
| `web/app.php` | `public/index.php`
25+
| `web/app_dev.php` | `public/index.php`
26+
27+
Then, upgrade the contents of your console script and your front controller:
28+
29+
* `bin/console`: https://github.com/symfony/recipes/blob/master/symfony/console/3.3/bin/console
30+
* `public/index.php`: https://github.com/symfony/recipes/blob/master/symfony/framework-bundle/3.3/public/index.php
31+
32+
Lastly, read the following article to add Symfony Flex to your application and
33+
upgrade the configuration files: https://symfony.com/doc/current/setup/flex.html
34+
35+
If you use Symfony components instead of the whole framework, you can find below
36+
the upgrading instructions for each individual bundle and component.
37+
438
ClassLoader
539
-----------
640

src/Symfony/Bridge/Monolog/composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@
3232
"suggest": {
3333
"symfony/http-kernel": "For using the debugging handlers together with the response life cycle of the HTTP kernel.",
3434
"symfony/console": "For the possibility to show log messages in console commands depending on verbosity settings. You need version ~2.3 of the console for it.",
35-
"symfony/event-dispatcher": "Needed when using log messages in console commands."
35+
"symfony/event-dispatcher": "Needed when using log messages in console commands.",
36+
"symfony/var-dumper": "For using the debugging handlers like the console handler or the log server handler."
3637
},
3738
"autoload": {
3839
"psr-4": { "Symfony\\Bridge\\Monolog\\": "" },

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

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,21 @@
88
{%- endblock textarea_widget %}
99

1010
{% block money_widget -%}
11-
<div class="input-group{{ group_class|default('') }}">
12-
{%- set append = money_pattern starts with '{{' -%}
13-
{%- if not append -%}
14-
<span class="input-group-addon">{{ money_pattern|replace({ '{{ widget }}':''}) }}</span>
15-
{%- endif -%}
11+
{% set prepend = not (money_pattern starts with '{{') %}
12+
{% set append = not (money_pattern ends with '}}') %}
13+
{% if prepend or append %}
14+
<div class="input-group{{ group_class|default('') }}">
15+
{% if prepend %}
16+
<span class="input-group-addon">{{ money_pattern|replace({ '{{ widget }}':''}) }}</span>
17+
{% endif %}
18+
{{- block('form_widget_simple') -}}
19+
{% if append %}
20+
<span class="input-group-addon">{{ money_pattern|replace({ '{{ widget }}':''}) }}</span>
21+
{% endif %}
22+
</div>
23+
{% else %}
1624
{{- block('form_widget_simple') -}}
17-
{%- if append -%}
18-
<span class="input-group-addon">{{ money_pattern|replace({ '{{ widget }}':''}) }}</span>
19-
{%- endif -%}
20-
</div>
25+
{% endif %}
2126
{%- endblock money_widget %}
2227

2328
{% block percent_widget -%}

src/Symfony/Bridge/Twig/Tests/Extension/WorkflowExtensionTest.php

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,6 @@ class WorkflowExtensionTest extends TestCase
2525

2626
protected function setUp()
2727
{
28-
if (!class_exists(Workflow::class)) {
29-
$this->markTestSkipped('The Workflow component is needed to run tests for this extension.');
30-
}
31-
3228
$places = array('ordered', 'waiting_for_payment', 'processed');
3329
$transitions = array(
3430
new Transition('t1', 'ordered', 'waiting_for_payment'),

src/Symfony/Bridge/Twig/composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
"twig/twig": "^1.35|^2.4.4"
2121
},
2222
"require-dev": {
23-
"fig/link-util": "^1.0",
2423
"symfony/asset": "~3.4|~4.0",
2524
"symfony/dependency-injection": "~3.4|~4.0",
2625
"symfony/finder": "~3.4|~4.0",
@@ -38,7 +37,8 @@
3837
"symfony/console": "~3.4|~4.0",
3938
"symfony/var-dumper": "~3.4|~4.0",
4039
"symfony/expression-language": "~3.4|~4.0",
41-
"symfony/web-link": "~3.4|~4.0"
40+
"symfony/web-link": "~3.4|~4.0",
41+
"symfony/workflow": "~3.4|~4.0"
4242
},
4343
"conflict": {
4444
"symfony/form": "<3.4",

src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
box-sizing: content-box;
4242
vertical-align: baseline;
4343
letter-spacing: normal;
44+
width: auto;
4445
}
4546

4647
.sf-toolbarreset {

src/Symfony/Bundle/WebServerBundle/Command/ServerLogCommand.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Bundle\WebServerBundle\Command;
1313

14+
use Monolog\Formatter\FormatterInterface;
1415
use Symfony\Bridge\Monolog\Formatter\ConsoleFormatter;
1516
use Symfony\Bridge\Monolog\Handler\ConsoleHandler;
1617
use Symfony\Component\Console\Command\Command;
@@ -37,6 +38,11 @@ public function isEnabled()
3738
return false;
3839
}
3940

41+
// based on a symfony/symfony package, it crashes due a missing FormatterInterface from monolog/monolog
42+
if (!class_exists(FormatterInterface::class)) {
43+
return false;
44+
}
45+
4046
return parent::isEnabled();
4147
}
4248

src/Symfony/Bundle/WebServerBundle/composer.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@
2929
"/Tests/"
3030
]
3131
},
32+
"suggest": {
33+
"symfony/monolog-bridge": "For using the log server.",
34+
"symfony/expression-language": "For using the filter option of the log server."
35+
},
3236
"minimum-stability": "dev",
3337
"extra": {
3438
"branch-alias": {

src/Symfony/Component/BrowserKit/Client.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,7 @@ protected function doRequestInProcess($request)
346346
{
347347
$deprecationsFile = tempnam(sys_get_temp_dir(), 'deprec');
348348
putenv('SYMFONY_DEPRECATIONS_SERIALIZE='.$deprecationsFile);
349+
$_ENV['SYMFONY_DEPRECATIONS_SERIALIZE'] = $deprecationsFile;
349350
$process = new PhpProcess($this->getScript($request), null, null);
350351
$process->run();
351352

src/Symfony/Component/Console/Event/ConsoleErrorEvent.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,6 @@ public function setExitCode(int $exitCode): void
5353

5454
public function getExitCode(): int
5555
{
56-
return null !== $this->exitCode ? $this->exitCode : ($this->error->getCode() ?: 1);
56+
return null !== $this->exitCode ? $this->exitCode : (is_int($this->error->getCode()) ? $this->error->getCode() : 1);
5757
}
5858
}

src/Symfony/Component/Debug/ErrorHandler.php

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,7 @@ public function handleException($exception, array $error = null)
499499
$exception = new FatalThrowableError($exception);
500500
}
501501
$type = $exception instanceof FatalErrorException ? $exception->getSeverity() : E_ERROR;
502+
$handlerException = null;
502503

503504
if (($this->loggedErrors & $type) || $exception instanceof FatalThrowableError) {
504505
if ($exception instanceof FatalErrorException) {
@@ -532,17 +533,19 @@ public function handleException($exception, array $error = null)
532533
}
533534
}
534535
}
535-
if (empty($this->exceptionHandler)) {
536-
throw $exception; // Give back $exception to the native handler
537-
}
538536
try {
539-
call_user_func($this->exceptionHandler, $exception);
537+
if (null !== $this->exceptionHandler) {
538+
return \call_user_func($this->exceptionHandler, $exception);
539+
}
540+
$handlerException = $handlerException ?: $exception;
540541
} catch (\Throwable $handlerException) {
541542
}
542-
if (isset($handlerException)) {
543-
$this->exceptionHandler = null;
544-
$this->handleException($handlerException);
543+
$this->exceptionHandler = null;
544+
if ($exception === $handlerException) {
545+
self::$reservedMemory = null; // Disable the fatal error handler
546+
throw $exception; // Give back $exception to the native handler
545547
}
548+
$this->handleException($handlerException);
546549
}
547550

548551
/**
@@ -558,15 +561,30 @@ public static function handleFatalError(array $error = null)
558561
return;
559562
}
560563

561-
self::$reservedMemory = null;
564+
$handler = self::$reservedMemory = null;
565+
$handlers = array();
562566

563-
$handler = set_error_handler('var_dump');
564-
$handler = is_array($handler) ? $handler[0] : null;
565-
restore_error_handler();
567+
while (!is_array($handler) || !$handler[0] instanceof self) {
568+
$handler = set_exception_handler('var_dump');
569+
restore_exception_handler();
566570

567-
if (!$handler instanceof self) {
571+
if (!$handler) {
572+
break;
573+
}
574+
restore_exception_handler();
575+
array_unshift($handlers, $handler);
576+
}
577+
foreach ($handlers as $h) {
578+
set_exception_handler($h);
579+
}
580+
if (!$handler) {
568581
return;
569582
}
583+
if ($handler !== $h) {
584+
$handler[0]->setExceptionHandler($h);
585+
}
586+
$handler = $handler[0];
587+
$handlers = array();
570588

571589
if ($exit = null === $error) {
572590
$error = error_get_last();
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--TEST--
2+
Test rethrowing in custom exception handler
3+
--FILE--
4+
<?php
5+
6+
namespace Symfony\Component\Debug;
7+
8+
$vendor = __DIR__;
9+
while (!file_exists($vendor.'/vendor')) {
10+
$vendor = dirname($vendor);
11+
}
12+
require $vendor.'/vendor/autoload.php';
13+
14+
if (true) {
15+
class TestLogger extends \Psr\Log\AbstractLogger
16+
{
17+
public function log($level, $message, array $context = array())
18+
{
19+
echo $message, "\n";
20+
}
21+
}
22+
}
23+
24+
set_exception_handler(function ($e) { echo 123; throw $e; });
25+
ErrorHandler::register()->setDefaultLogger(new TestLogger());
26+
ini_set('display_errors', 1);
27+
28+
throw new \Exception('foo');
29+
30+
?>
31+
--EXPECTF--
32+
Uncaught Exception: foo
33+
123
34+
Fatal error: Uncaught %s:25
35+
Stack trace:
36+
%a
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
--TEST--
2+
Test catching fatal errors when handlers are nested
3+
--FILE--
4+
<?php
5+
6+
namespace Symfony\Component\Debug;
7+
8+
$vendor = __DIR__;
9+
while (!file_exists($vendor.'/vendor')) {
10+
$vendor = dirname($vendor);
11+
}
12+
require $vendor.'/vendor/autoload.php';
13+
14+
Debug::enable();
15+
ini_set('display_errors', 0);
16+
17+
$eHandler = set_error_handler('var_dump');
18+
$xHandler = set_exception_handler('var_dump');
19+
20+
var_dump(array(
21+
$eHandler[0] === $xHandler[0] ? 'Error and exception handlers do match' : 'Error and exception handlers are different',
22+
));
23+
24+
$eHandler[0]->setExceptionHandler('print_r');
25+
26+
if (true) {
27+
class Broken implements \Serializable {};
28+
}
29+
30+
?>
31+
--EXPECTF--
32+
array(1) {
33+
[0]=>
34+
string(37) "Error and exception handlers do match"
35+
}
36+
object(Symfony\Component\Debug\Exception\FatalErrorException)#%d (%d) {
37+
["message":protected]=>
38+
string(199) "Error: Class Symfony\Component\Debug\Broken contains 2 abstract methods and must therefore be declared abstract or implement the remaining methods (Serializable::serialize, Serializable::unserialize)"
39+
%a
40+
}

src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Component\DependencyInjection\Compiler;
1313

14+
use Symfony\Component\Config\Resource\ClassExistenceResource;
1415
use Symfony\Component\DependencyInjection\ContainerBuilder;
1516
use Symfony\Component\DependencyInjection\Definition;
1617
use Symfony\Component\DependencyInjection\Exception\AutowiringFailedException;
@@ -314,7 +315,17 @@ private function set(string $type, string $id)
314315
private function createTypeNotFoundMessage(TypedReference $reference, $label)
315316
{
316317
if (!$r = $this->container->getReflectionClass($type = $reference->getType(), false)) {
317-
$message = sprintf('has type "%s" but this class cannot be loaded.', $type);
318+
// either $type does not exist or a parent class does not exist
319+
try {
320+
$resource = new ClassExistenceResource($type, false);
321+
// isFresh() will explode ONLY if a parent class/trait does not exist
322+
$resource->isFresh(0);
323+
$parentMsg = false;
324+
} catch (\ReflectionException $e) {
325+
$parentMsg = $e->getMessage();
326+
}
327+
328+
$message = sprintf('has type "%s" but this class %s.', $type, $parentMsg ? sprintf('is missing a parent class (%s)', $parentMsg) : 'was not found');
318329
} else {
319330
$message = $this->container->has($type) ? 'this service is abstract' : 'no such service exists';
320331
$message = sprintf('references %s "%s" but %s.%s', $r->isInterface() ? 'interface' : 'class', $type, $message, $this->createTypeAlternatives($reference));

src/Symfony/Component/DependencyInjection/Compiler/RegisterServiceSubscribersPass.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ protected function processValue($value, $isRoot = false)
9494
throw new InvalidArgumentException(sprintf('Service %s not exist in the map returned by "%s::getSubscribedServices()" for service "%s".', $message, $class, $this->currentId));
9595
}
9696

97-
$value->addTag('container.service_subscriber.locator', array('id' => (string) ServiceLocatorTagPass::register($this->container, $subscriberMap)));
97+
$value->addTag('container.service_subscriber.locator', array('id' => (string) ServiceLocatorTagPass::register($this->container, $subscriberMap, $this->currentId)));
9898

9999
return parent::processValue($value);
100100
}

src/Symfony/Component/DependencyInjection/Compiler/ServiceLocatorTagPass.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,11 @@ protected function processValue($value, $isRoot = false)
7272
/**
7373
* @param ContainerBuilder $container
7474
* @param Reference[] $refMap
75+
* @param string|null $callerId
7576
*
7677
* @return Reference
7778
*/
78-
public static function register(ContainerBuilder $container, array $refMap)
79+
public static function register(ContainerBuilder $container, array $refMap, $callerId = null)
7980
{
8081
foreach ($refMap as $id => $ref) {
8182
if (!$ref instanceof Reference) {
@@ -94,6 +95,18 @@ public static function register(ContainerBuilder $container, array $refMap)
9495
$container->setDefinition($id, $locator);
9596
}
9697

98+
if (null !== $callerId) {
99+
$locatorId = $id;
100+
// Locators are shared when they hold the exact same list of factories;
101+
// to have them specialized per consumer service, we use a cloning factory
102+
// to derivate customized instances from the prototype one.
103+
$container->register($id .= '.'.$callerId, ServiceLocator::class)
104+
->setPublic(false)
105+
->setFactory(array(new Reference($locatorId), 'withContext'))
106+
->addArgument($callerId)
107+
->addArgument(new Reference('service_container'));
108+
}
109+
97110
return new Reference($id);
98111
}
99112
}

0 commit comments

Comments
 (0)