PDF rausgenommen

This commit is contained in:
aschwarz
2023-01-23 11:03:31 +01:00
parent 82d562a322
commit a6523903eb
28078 changed files with 4247552 additions and 2 deletions

View File

@ -0,0 +1,3 @@
composer.lock
phpunit.xml
vendor/

View File

@ -0,0 +1,12 @@
CHANGELOG
=========
1.0.0
-----
* added `Service\ResetInterface` to provide a way to reset an object to its initial state
* added `Translation\TranslatorInterface` and `Translation\TranslatorTrait`
* added `Cache` contract to extend PSR-6 with tag invalidation, callback-based computation and stampede protection
* added `Service\ServiceSubscriberInterface` to declare the dependencies of a class that consumes a service locator
* added `Service\ServiceSubscriberTrait` to implement `Service\ServiceSubscriberInterface` using methods' return types
* added `Service\ServiceLocatorTrait` to help implement PSR-11 service locators

View File

@ -0,0 +1,57 @@
<?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\Contracts\Cache;
use Psr\Cache\CacheItemInterface;
use Psr\Cache\InvalidArgumentException;
/**
* Covers most simple to advanced caching needs.
*
* @author Nicolas Grekas <p@tchwork.com>
*/
interface CacheInterface
{
/**
* Fetches a value from the pool or computes it if not found.
*
* On cache misses, a callback is called that should return the missing value.
* This callback is given a PSR-6 CacheItemInterface instance corresponding to the
* requested key, that could be used e.g. for expiration control. It could also
* be an ItemInterface instance when its additional features are needed.
*
* @param string $key The key of the item to retrieve from the cache
* @param callable|CallbackInterface $callback Should return the computed value for the given key/item
* @param float|null $beta A float that, as it grows, controls the likeliness of triggering
* early expiration. 0 disables it, INF forces immediate expiration.
* The default (or providing null) is implementation dependent but should
* typically be 1.0, which should provide optimal stampede protection.
* See https://en.wikipedia.org/wiki/Cache_stampede#Probabilistic_early_expiration
* @param array &$metadata The metadata of the cached item {@see ItemInterface::getMetadata()}
*
* @return mixed The value corresponding to the provided key
*
* @throws InvalidArgumentException When $key is not valid or when $beta is negative
*/
public function get(string $key, callable $callback, float $beta = null, array &$metadata = null);
/**
* Removes an item from the pool.
*
* @param string $key The key to delete
*
* @throws InvalidArgumentException When $key is not valid
*
* @return bool True if the item was successfully removed, false if there was any error
*/
public function delete(string $key): bool;
}

View File

@ -0,0 +1,71 @@
<?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\Contracts\Cache;
use Psr\Cache\CacheItemPoolInterface;
use Psr\Cache\InvalidArgumentException;
/**
* An implementation of CacheInterface for PSR-6 CacheItemPoolInterface classes.
*
* @author Nicolas Grekas <p@tchwork.com>
*/
trait CacheTrait
{
/**
* {@inheritdoc}
*/
public function get(string $key, callable $callback, float $beta = null, array &$metadata = null)
{
return $this->doGet($this, $key, $callback, $beta, $metadata);
}
/**
* {@inheritdoc}
*/
public function delete(string $key): bool
{
return $this->deleteItem($key);
}
private function doGet(CacheItemPoolInterface $pool, string $key, callable $callback, ?float $beta, array &$metadata = null)
{
if (0 > $beta = $beta ?? 1.0) {
throw new class(sprintf('Argument "$beta" provided to "%s::get()" must be a positive number, %f given.', \get_class($this), $beta)) extends \InvalidArgumentException implements InvalidArgumentException {
};
}
$item = $pool->getItem($key);
$recompute = !$item->isHit() || INF === $beta;
$metadata = $item instanceof ItemInterface ? $item->getMetadata() : array();
if (!$recompute && $metadata) {
$expiry = $metadata[ItemInterface::METADATA_EXPIRY] ?? false;
$ctime = $metadata[ItemInterface::METADATA_CTIME] ?? false;
if ($recompute = $ctime && $expiry && $expiry <= microtime(true) - $ctime / 1000 * $beta * log(random_int(1, PHP_INT_MAX) / PHP_INT_MAX)) {
// force applying defaultLifetime to expiry
$item->expiresAt(null);
}
}
if ($recompute) {
$save = true;
$item->set($callback($item, $save));
if ($save) {
$pool->save($item);
}
}
return $item->get();
}
}

View File

@ -0,0 +1,30 @@
<?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\Contracts\Cache;
use Psr\Cache\CacheItemInterface;
/**
* Computes and returns the cached value of an item.
*
* @author Nicolas Grekas <p@tchwork.com>
*/
interface CallbackInterface
{
/**
* @param CacheItemInterface|ItemInterface $item The item to compute the value for
* @param bool &$save Should be set to false when the value should not be saved in the pool
*
* @return mixed The computed value for the passed item
*/
public function __invoke(CacheItemInterface $item, bool &$save);
}

View File

@ -0,0 +1,60 @@
<?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\Contracts\Cache;
use Psr\Cache\CacheException;
use Psr\Cache\CacheItemInterface;
use Psr\Cache\InvalidArgumentException;
/**
* Augments PSR-6's CacheItemInterface with support for tags and metadata.
*
* @author Nicolas Grekas <p@tchwork.com>
*/
interface ItemInterface extends CacheItemInterface
{
/**
* References the Unix timestamp stating when the item will expire.
*/
const METADATA_EXPIRY = 'expiry';
/**
* References the time the item took to be created, in milliseconds.
*/
const METADATA_CTIME = 'ctime';
/**
* References the list of tags that were assigned to the item, as string[].
*/
const METADATA_TAGS = 'tags';
/**
* Adds a tag to a cache item.
*
* Tags are strings that follow the same validation rules as keys.
*
* @param string|string[] $tags A tag or array of tags
*
* @return $this
*
* @throws InvalidArgumentException When $tag is not valid
* @throws CacheException When the item comes from a pool that is not tag-aware
*/
public function tag($tags): self;
/**
* Returns a list of metadata info that were saved alongside with the cached value.
*
* See ItemInterface::METADATA_* consts for keys potentially found in the returned array.
*/
public function getMetadata(): array;
}

View File

@ -0,0 +1,38 @@
<?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\Contracts\Cache;
use Psr\Cache\InvalidArgumentException;
/**
* Allows invalidating cached items using tags.
*
* @author Nicolas Grekas <p@tchwork.com>
*/
interface TagAwareCacheInterface extends CacheInterface
{
/**
* Invalidates cached items using tags.
*
* When implemented on a PSR-6 pool, invalidation should not apply
* to deferred items. Instead, they should be committed as usual.
* This allows replacing old tagged values by new ones without
* race conditions.
*
* @param string[] $tags An array of tags to invalidate
*
* @return bool True on success
*
* @throws InvalidArgumentException When $tags is not valid
*/
public function invalidateTags(array $tags);
}

View File

@ -0,0 +1,19 @@
Copyright (c) 2018 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -0,0 +1,70 @@
Symfony Contracts
=================
A set of abstractions extracted out of the Symfony components.
Can be used to build on semantics that the Symfony components proved useful - and
that already have battle tested implementations.
Design Principles
-----------------
* contracts are split by domain, each into their own sub-namespaces;
* contracts are small and consistent sets of PHP interfaces, traits, normative
docblocks and reference test suites when applicable, etc.;
* all contracts must have a proven implementation to enter this repository;
* they must be backward compatible with existing Symfony components.
Packages that implement specific contracts should list them in the "provide"
section of their "composer.json" file, using the `symfony/*-contracts-implementation`
convention (e.g. `"provide": { "symfony/cache-contracts-implementation": "1.0" }`).
FAQ
---
### How to use this package?
The abstractions in this package are useful to achieve loose coupling and
interoperability. By using the provided interfaces as type hints, you are able
to reuse any implementations that match their contracts. It could be a Symfony
component, or another one provided by the PHP community at large.
Depending on their semantics, some interfaces can be combined with autowiring to
seamlessly inject a service in your classes.
Others might be useful as labeling interfaces, to hint about a specific behavior
that could be enabled when using autoconfiguration or manual service tagging (or
any other means provided by your framework.)
### How is this different from PHP-FIG's PSRs?
When applicable, the provided contracts are built on top of PHP-FIG's PSRs. But
the group has different goals and different processes. Here, we're focusing on
providing abstractions that are useful on their own while still compatible with
implementations provided by Symfony. Although not the main target, we hope that
the declared contracts will directly or indirectly contribute to the PHP-FIG.
### Why isn't this package split into several packages?
Putting all interfaces in one package eases discoverability and dependency
management. Instead of dealing with a myriad of small packages and the
corresponding matrix of versions, you just need to deal with one package and one
version. Also when using IDE autocompletion or just reading the source code, it
makes it easier to figure out which contracts are provided.
There are two downsides to this approach: you may have unused files in your
`vendor/` directory, and in the future, it will be impossible to use two
different sub-namespaces in different major versions of the package. For the
"unused files" downside, it has no practical consequences: their file sizes are
very small, and there is no performance overhead at all since they are never
loaded. For major versions, this package follows the Symfony BC + deprecation
policies, with an additional restriction to never remove deprecated interfaces.
Resources
---------
* [Documentation](https://symfony.com/doc/current/components/contracts.html)
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
* [Report issues](https://github.com/symfony/symfony/issues) and
[send Pull Requests](https://github.com/symfony/symfony/pulls)
in the [main Symfony repository](https://github.com/symfony/symfony)

View File

@ -0,0 +1,30 @@
<?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\Contracts\Service;
/**
* Provides a way to reset an object to its initial state.
*
* When calling the "reset()" method on an object, it should be put back to its
* initial state. This usually means clearing any internal buffers and forwarding
* the call to internal dependencies. All properties of the object should be put
* back to the same state it had when it was first ready to use.
*
* This method could be called, for example, to recycle objects that are used as
* services, so that they can be used to handle several requests in the same
* process loop (note that we advise making your services stateless instead of
* implementing this interface when possible.)
*/
interface ResetInterface
{
public function reset();
}

View File

@ -0,0 +1,97 @@
<?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\Contracts\Service;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
/**
* A trait to help implement PSR-11 service locators.
*
* @author Robin Chalas <robin.chalas@gmail.com>
* @author Nicolas Grekas <p@tchwork.com>
*/
trait ServiceLocatorTrait
{
private $factories;
private $loading = array();
/**
* @param callable[] $factories
*/
public function __construct(array $factories)
{
$this->factories = $factories;
}
/**
* {@inheritdoc}
*/
public function has($id)
{
return isset($this->factories[$id]);
}
/**
* {@inheritdoc}
*/
public function get($id)
{
if (!isset($this->factories[$id])) {
throw $this->createNotFoundException($id);
}
if (isset($this->loading[$id])) {
$ids = array_values($this->loading);
$ids = \array_slice($this->loading, array_search($id, $ids));
$ids[] = $id;
throw $this->createCircularReferenceException($id, $ids);
}
$this->loading[$id] = $id;
try {
return $this->factories[$id]($this);
} finally {
unset($this->loading[$id]);
}
}
private function createNotFoundException(string $id): NotFoundExceptionInterface
{
if (!$alternatives = array_keys($this->factories)) {
$message = 'is empty...';
} else {
$last = array_pop($alternatives);
if ($alternatives) {
$message = sprintf('only knows about the "%s" and "%s" services.', implode('", "', $alternatives), $last);
} else {
$message = sprintf('only knows about the "%s" service.', $last);
}
}
if ($this->loading) {
$message = sprintf('The service "%s" has a dependency on a non-existent service "%s". This locator %s', end($this->loading), $id, $message);
} else {
$message = sprintf('Service "%s" not found: the current service locator %s', $id, $message);
}
return new class($message) extends \InvalidArgumentException implements NotFoundExceptionInterface {
};
}
private function createCircularReferenceException(string $id, array $path): ContainerExceptionInterface
{
return new class(sprintf('Circular reference detected for service "%s", path: "%s".', $id, implode(' -> ', $path))) extends \RuntimeException implements ContainerExceptionInterface {
};
}
}

View File

@ -0,0 +1,53 @@
<?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\Contracts\Service;
/**
* A ServiceSubscriber exposes its dependencies via the static {@link getSubscribedServices} method.
*
* The getSubscribedServices method returns an array of service types required by such instances,
* optionally keyed by the service names used internally. Service types that start with an interrogation
* mark "?" are optional, while the other ones are mandatory service dependencies.
*
* The injected service locators SHOULD NOT allow access to any other services not specified by the method.
*
* It is expected that ServiceSubscriber instances consume PSR-11-based service locators internally.
* This interface does not dictate any injection method for these service locators, although constructor
* injection is recommended.
*
* @author Nicolas Grekas <p@tchwork.com>
*/
interface ServiceSubscriberInterface
{
/**
* Returns an array of service types required by such instances, optionally keyed by the service names used internally.
*
* For mandatory dependencies:
*
* * array('logger' => 'Psr\Log\LoggerInterface') means the objects use the "logger" name
* internally to fetch a service which must implement Psr\Log\LoggerInterface.
* * array('loggers' => 'Psr\Log\LoggerInterface[]') means the objects use the "loggers" name
* internally to fetch an iterable of Psr\Log\LoggerInterface instances.
* * array('Psr\Log\LoggerInterface') is a shortcut for
* * array('Psr\Log\LoggerInterface' => 'Psr\Log\LoggerInterface')
*
* otherwise:
*
* * array('logger' => '?Psr\Log\LoggerInterface') denotes an optional dependency
* * array('loggers' => '?Psr\Log\LoggerInterface[]') denotes an optional iterable dependency
* * array('?Psr\Log\LoggerInterface') is a shortcut for
* * array('Psr\Log\LoggerInterface' => '?Psr\Log\LoggerInterface')
*
* @return array The required service types, optionally keyed by service names
*/
public static function getSubscribedServices();
}

View File

@ -0,0 +1,61 @@
<?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\Contracts\Service;
use Psr\Container\ContainerInterface;
/**
* Implementation of ServiceSubscriberInterface that determines subscribed services from
* private method return types. Service ids are available as "ClassName::methodName".
*
* @author Kevin Bond <kevinbond@gmail.com>
*/
trait ServiceSubscriberTrait
{
/** @var ContainerInterface */
private $container;
public static function getSubscribedServices(): array
{
static $services;
if (null !== $services) {
return $services;
}
$services = \is_callable(array('parent', __FUNCTION__)) ? parent::getSubscribedServices() : array();
foreach ((new \ReflectionClass(self::class))->getMethods() as $method) {
if ($method->isStatic() || $method->isAbstract() || $method->isGenerator() || $method->isInternal() || $method->getNumberOfRequiredParameters()) {
continue;
}
if (self::class === $method->getDeclaringClass()->name && ($returnType = $method->getReturnType()) && !$returnType->isBuiltin()) {
$services[self::class.'::'.$method->name] = '?'.$returnType->getName();
}
}
return $services;
}
/**
* @required
*/
public function setContainer(ContainerInterface $container)
{
$this->container = $container;
if (\is_callable(array('parent', __FUNCTION__))) {
return parent::setContainer($container);
}
}
}

View File

@ -0,0 +1,165 @@
<?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\Contracts\Tests\Cache;
use PHPUnit\Framework\TestCase;
use Psr\Cache\CacheItemInterface;
use Psr\Cache\CacheItemPoolInterface;
use Symfony\Contracts\Cache\CacheTrait;
/**
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
class CacheTraitTest extends TestCase
{
public function testSave()
{
$item = $this->getMockBuilder(CacheItemInterface::class)->getMock();
$item->method('set')
->willReturn($item);
$item->method('isHit')
->willReturn(false);
$item->expects($this->once())
->method('set')
->with('computed data');
$cache = $this->getMockBuilder(TestPool::class)
->setMethods(array('getItem', 'save'))
->getMock();
$cache->expects($this->once())
->method('getItem')
->with('key')
->willReturn($item);
$cache->expects($this->once())
->method('save');
$callback = function (CacheItemInterface $item) {
return 'computed data';
};
$cache->get('key', $callback);
}
public function testNoCallbackCallOnHit()
{
$item = $this->getMockBuilder(CacheItemInterface::class)->getMock();
$item->method('isHit')
->willReturn(true);
$item->expects($this->never())
->method('set');
$cache = $this->getMockBuilder(TestPool::class)
->setMethods(array('getItem', 'save'))
->getMock();
$cache->expects($this->once())
->method('getItem')
->with('key')
->willReturn($item);
$cache->expects($this->never())
->method('save');
$callback = function (CacheItemInterface $item) {
$this->assertTrue(false, 'This code should never be reached');
};
$cache->get('key', $callback);
}
public function testRecomputeOnBetaInf()
{
$item = $this->getMockBuilder(CacheItemInterface::class)->getMock();
$item->method('set')
->willReturn($item);
$item->method('isHit')
// We want to recompute even if it is a hit
->willReturn(true);
$item->expects($this->once())
->method('set')
->with('computed data');
$cache = $this->getMockBuilder(TestPool::class)
->setMethods(array('getItem', 'save'))
->getMock();
$cache->expects($this->once())
->method('getItem')
->with('key')
->willReturn($item);
$cache->expects($this->once())
->method('save');
$callback = function (CacheItemInterface $item) {
return 'computed data';
};
$cache->get('key', $callback, INF);
}
public function testExceptionOnNegativeBeta()
{
$cache = $this->getMockBuilder(TestPool::class)
->setMethods(array('getItem', 'save'))
->getMock();
$callback = function (CacheItemInterface $item) {
return 'computed data';
};
$this->expectException(\InvalidArgumentException::class);
$cache->get('key', $callback, -2);
}
}
class TestPool implements CacheItemPoolInterface
{
use CacheTrait;
public function hasItem($key)
{
}
public function deleteItem($key)
{
}
public function deleteItems(array $keys = array())
{
}
public function getItem($key)
{
}
public function getItems(array $key = array())
{
}
public function saveDeferred(CacheItemInterface $item)
{
}
public function save(CacheItemInterface $item)
{
}
public function commit()
{
}
public function clear()
{
}
}

View File

@ -0,0 +1,94 @@
<?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\Contracts\Tests\Service;
use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerInterface;
use Symfony\Contracts\Service\ServiceLocatorTrait;
class ServiceLocatorTest extends TestCase
{
public function getServiceLocator(array $factories)
{
return new class($factories) implements ContainerInterface {
use ServiceLocatorTrait;
};
}
public function testHas()
{
$locator = $this->getServiceLocator(array(
'foo' => function () { return 'bar'; },
'bar' => function () { return 'baz'; },
function () { return 'dummy'; },
));
$this->assertTrue($locator->has('foo'));
$this->assertTrue($locator->has('bar'));
$this->assertFalse($locator->has('dummy'));
}
public function testGet()
{
$locator = $this->getServiceLocator(array(
'foo' => function () { return 'bar'; },
'bar' => function () { return 'baz'; },
));
$this->assertSame('bar', $locator->get('foo'));
$this->assertSame('baz', $locator->get('bar'));
}
public function testGetDoesNotMemoize()
{
$i = 0;
$locator = $this->getServiceLocator(array(
'foo' => function () use (&$i) {
++$i;
return 'bar';
},
));
$this->assertSame('bar', $locator->get('foo'));
$this->assertSame('bar', $locator->get('foo'));
$this->assertSame(2, $i);
}
/**
* @expectedException \Psr\Container\NotFoundExceptionInterface
* @expectedExceptionMessage The service "foo" has a dependency on a non-existent service "bar". This locator only knows about the "foo" service.
*/
public function testThrowsOnUndefinedInternalService()
{
$locator = $this->getServiceLocator(array(
'foo' => function () use (&$locator) { return $locator->get('bar'); },
));
$locator->get('foo');
}
/**
* @expectedException \Psr\Container\ContainerExceptionInterface
* @expectedExceptionMessage Circular reference detected for service "bar", path: "bar -> baz -> bar".
*/
public function testThrowsOnCircularReference()
{
$locator = $this->getServiceLocator(array(
'foo' => function () use (&$locator) { return $locator->get('bar'); },
'bar' => function () use (&$locator) { return $locator->get('baz'); },
'baz' => function () use (&$locator) { return $locator->get('bar'); },
));
$locator->get('foo');
}
}

View File

@ -0,0 +1,65 @@
<?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\Contracts\Tests\Service;
use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerInterface;
use Symfony\Contracts\Service\ServiceLocatorTrait;
use Symfony\Contracts\Service\ServiceSubscriberInterface;
use Symfony\Contracts\Service\ServiceSubscriberTrait;
class ServiceSubscriberTraitTest extends TestCase
{
public function testMethodsOnParentsAndChildrenAreIgnoredInGetSubscribedServices()
{
$expected = array(TestService::class.'::aService' => '?Symfony\Contracts\Tests\Service\Service2');
$this->assertEquals($expected, ChildTestService::getSubscribedServices());
}
public function testSetContainerIsCalledOnParent()
{
$container = new class(array()) implements ContainerInterface {
use ServiceLocatorTrait;
};
$this->assertSame($container, (new TestService())->setContainer($container));
}
}
class ParentTestService
{
public function aParentService(): Service1
{
}
public function setContainer(ContainerInterface $container)
{
return $container;
}
}
class TestService extends ParentTestService implements ServiceSubscriberInterface
{
use ServiceSubscriberTrait;
public function aService(): Service2
{
}
}
class ChildTestService extends TestService
{
public function aChildService(): Service3
{
}
}

View File

@ -0,0 +1,353 @@
<?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\Contracts\Tests\Translation;
use PHPUnit\Framework\TestCase;
use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\Contracts\Translation\TranslatorTrait;
/**
* Test should cover all languages mentioned on http://translate.sourceforge.net/wiki/l10n/pluralforms
* and Plural forms mentioned on http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms.
*
* See also https://developer.mozilla.org/en/Localization_and_Plurals which mentions 15 rules having a maximum of 6 forms.
* The mozilla code is also interesting to check for.
*
* As mentioned by chx http://drupal.org/node/1273968 we can cover all by testing number from 0 to 199
*
* The goal to cover all languages is to far fetched so this test case is smaller.
*
* @author Clemens Tolboom clemens@build2be.nl
*/
class TranslatorTest extends TestCase
{
public function getTranslator()
{
return new class() implements TranslatorInterface {
use TranslatorTrait;
};
}
/**
* @dataProvider getTransTests
*/
public function testTrans($expected, $id, $parameters)
{
$translator = $this->getTranslator();
$this->assertEquals($expected, $translator->trans($id, $parameters));
}
/**
* @dataProvider getTransChoiceTests
*/
public function testTransChoiceWithExplicitLocale($expected, $id, $number)
{
$translator = $this->getTranslator();
$translator->setLocale('en');
$this->assertEquals($expected, $translator->trans($id, array('%count%' => $number)));
}
/**
* @dataProvider getTransChoiceTests
*/
public function testTransChoiceWithDefaultLocale($expected, $id, $number)
{
\Locale::setDefault('en');
$translator = $this->getTranslator();
$this->assertEquals($expected, $translator->trans($id, array('%count%' => $number)));
}
public function testGetSetLocale()
{
$translator = $this->getTranslator();
$translator->setLocale('en');
$this->assertEquals('en', $translator->getLocale());
}
/**
* @requires extension intl
*/
public function testGetLocaleReturnsDefaultLocaleIfNotSet()
{
$translator = $this->getTranslator();
\Locale::setDefault('pt_BR');
$this->assertEquals('pt_BR', $translator->getLocale());
\Locale::setDefault('en');
$this->assertEquals('en', $translator->getLocale());
}
public function getTransTests()
{
return array(
array('Symfony is great!', 'Symfony is great!', array()),
array('Symfony is awesome!', 'Symfony is %what%!', array('%what%' => 'awesome')),
);
}
public function getTransChoiceTests()
{
return array(
array('There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0),
array('There is one apple', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 1),
array('There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10),
array('There are 0 apples', 'There is 1 apple|There are %count% apples', 0),
array('There is 1 apple', 'There is 1 apple|There are %count% apples', 1),
array('There are 10 apples', 'There is 1 apple|There are %count% apples', 10),
// custom validation messages may be coded with a fixed value
array('There are 2 apples', 'There are 2 apples', 2),
);
}
/**
* @dataProvider getInternal
*/
public function testInterval($expected, $number, $interval)
{
$translator = $this->getTranslator();
$this->assertEquals($expected, $translator->trans($interval.' foo|[1,Inf[ bar', array('%count%' => $number)));
}
public function getInternal()
{
return array(
array('foo', 3, '{1,2, 3 ,4}'),
array('bar', 10, '{1,2, 3 ,4}'),
array('bar', 3, '[1,2]'),
array('foo', 1, '[1,2]'),
array('foo', 2, '[1,2]'),
array('bar', 1, ']1,2['),
array('bar', 2, ']1,2['),
array('foo', log(0), '[-Inf,2['),
array('foo', -log(0), '[-2,+Inf]'),
);
}
/**
* @dataProvider getChooseTests
*/
public function testChoose($expected, $id, $number)
{
$translator = $this->getTranslator();
$this->assertEquals($expected, $translator->trans($id, array('%count%' => $number)));
}
public function testReturnMessageIfExactlyOneStandardRuleIsGiven()
{
$translator = $this->getTranslator();
$this->assertEquals('There are two apples', $translator->trans('There are two apples', array('%count%' => 2)));
}
/**
* @dataProvider getNonMatchingMessages
* @expectedException \InvalidArgumentException
*/
public function testThrowExceptionIfMatchingMessageCannotBeFound($id, $number)
{
$translator = $this->getTranslator();
$translator->trans($id, array('%count%' => $number));
}
public function getNonMatchingMessages()
{
return array(
array('{0} There are no apples|{1} There is one apple', 2),
array('{1} There is one apple|]1,Inf] There are %count% apples', 0),
array('{1} There is one apple|]2,Inf] There are %count% apples', 2),
array('{0} There are no apples|There is one apple', 2),
);
}
public function getChooseTests()
{
return array(
array('There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0),
array('There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0),
array('There are no apples', '{0}There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0),
array('There is one apple', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 1),
array('There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10),
array('There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf]There are %count% apples', 10),
array('There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10),
array('There are 0 apples', 'There is one apple|There are %count% apples', 0),
array('There is one apple', 'There is one apple|There are %count% apples', 1),
array('There are 10 apples', 'There is one apple|There are %count% apples', 10),
array('There are 0 apples', 'one: There is one apple|more: There are %count% apples', 0),
array('There is one apple', 'one: There is one apple|more: There are %count% apples', 1),
array('There are 10 apples', 'one: There is one apple|more: There are %count% apples', 10),
array('There are no apples', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 0),
array('There is one apple', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 1),
array('There are 10 apples', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 10),
array('', '{0}|{1} There is one apple|]1,Inf] There are %count% apples', 0),
array('', '{0} There are no apples|{1}|]1,Inf] There are %count% apples', 1),
// Indexed only tests which are Gettext PoFile* compatible strings.
array('There are 0 apples', 'There is one apple|There are %count% apples', 0),
array('There is one apple', 'There is one apple|There are %count% apples', 1),
array('There are 2 apples', 'There is one apple|There are %count% apples', 2),
// Tests for float numbers
array('There is almost one apple', '{0} There are no apples|]0,1[ There is almost one apple|{1} There is one apple|[1,Inf] There is more than one apple', 0.7),
array('There is one apple', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 1),
array('There is more than one apple', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 1.7),
array('There are no apples', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 0),
array('There are no apples', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 0.0),
array('There are no apples', '{0.0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 0),
// Test texts with new-lines
// with double-quotes and \n in id & double-quotes and actual newlines in text
array("This is a text with a\n new-line in it. Selector = 0.", '{0}This is a text with a
new-line in it. Selector = 0.|{1}This is a text with a
new-line in it. Selector = 1.|[1,Inf]This is a text with a
new-line in it. Selector > 1.', 0),
// with double-quotes and \n in id and single-quotes and actual newlines in text
array("This is a text with a\n new-line in it. Selector = 1.", '{0}This is a text with a
new-line in it. Selector = 0.|{1}This is a text with a
new-line in it. Selector = 1.|[1,Inf]This is a text with a
new-line in it. Selector > 1.', 1),
array("This is a text with a\n new-line in it. Selector > 1.", '{0}This is a text with a
new-line in it. Selector = 0.|{1}This is a text with a
new-line in it. Selector = 1.|[1,Inf]This is a text with a
new-line in it. Selector > 1.', 5),
// with double-quotes and id split accros lines
array('This is a text with a
new-line in it. Selector = 1.', '{0}This is a text with a
new-line in it. Selector = 0.|{1}This is a text with a
new-line in it. Selector = 1.|[1,Inf]This is a text with a
new-line in it. Selector > 1.', 1),
// with single-quotes and id split accros lines
array('This is a text with a
new-line in it. Selector > 1.', '{0}This is a text with a
new-line in it. Selector = 0.|{1}This is a text with a
new-line in it. Selector = 1.|[1,Inf]This is a text with a
new-line in it. Selector > 1.', 5),
// with single-quotes and \n in text
array('This is a text with a\nnew-line in it. Selector = 0.', '{0}This is a text with a\nnew-line in it. Selector = 0.|{1}This is a text with a\nnew-line in it. Selector = 1.|[1,Inf]This is a text with a\nnew-line in it. Selector > 1.', 0),
// with double-quotes and id split accros lines
array("This is a text with a\nnew-line in it. Selector = 1.", "{0}This is a text with a\nnew-line in it. Selector = 0.|{1}This is a text with a\nnew-line in it. Selector = 1.|[1,Inf]This is a text with a\nnew-line in it. Selector > 1.", 1),
// esacape pipe
array('This is a text with | in it. Selector = 0.', '{0}This is a text with || in it. Selector = 0.|{1}This is a text with || in it. Selector = 1.', 0),
// Empty plural set (2 plural forms) from a .PO file
array('', '|', 1),
// Empty plural set (3 plural forms) from a .PO file
array('', '||', 1),
);
}
/**
* @dataProvider failingLangcodes
*/
public function testFailedLangcodes($nplural, $langCodes)
{
$matrix = $this->generateTestData($langCodes);
$this->validateMatrix($nplural, $matrix, false);
}
/**
* @dataProvider successLangcodes
*/
public function testLangcodes($nplural, $langCodes)
{
$matrix = $this->generateTestData($langCodes);
$this->validateMatrix($nplural, $matrix);
}
/**
* This array should contain all currently known langcodes.
*
* As it is impossible to have this ever complete we should try as hard as possible to have it almost complete.
*
* @return array
*/
public function successLangcodes()
{
return array(
array('1', array('ay', 'bo', 'cgg', 'dz', 'id', 'ja', 'jbo', 'ka', 'kk', 'km', 'ko', 'ky')),
array('2', array('nl', 'fr', 'en', 'de', 'de_GE', 'hy', 'hy_AM')),
array('3', array('be', 'bs', 'cs', 'hr')),
array('4', array('cy', 'mt', 'sl')),
array('6', array('ar')),
);
}
/**
* This array should be at least empty within the near future.
*
* This both depends on a complete list trying to add above as understanding
* the plural rules of the current failing languages.
*
* @return array with nplural together with langcodes
*/
public function failingLangcodes()
{
return array(
array('1', array('fa')),
array('2', array('jbo')),
array('3', array('cbs')),
array('4', array('gd', 'kw')),
array('5', array('ga')),
);
}
/**
* We validate only on the plural coverage. Thus the real rules is not tested.
*
* @param string $nplural Plural expected
* @param array $matrix Containing langcodes and their plural index values
* @param bool $expectSuccess
*/
protected function validateMatrix($nplural, $matrix, $expectSuccess = true)
{
foreach ($matrix as $langCode => $data) {
$indexes = array_flip($data);
if ($expectSuccess) {
$this->assertEquals($nplural, \count($indexes), "Langcode '$langCode' has '$nplural' plural forms.");
} else {
$this->assertNotEquals((int) $nplural, \count($indexes), "Langcode '$langCode' has '$nplural' plural forms.");
}
}
}
protected function generateTestData($langCodes)
{
$translator = new class() {
use TranslatorTrait {
getPluralizationRule as public;
}
};
$matrix = array();
foreach ($langCodes as $langCode) {
for ($count = 0; $count < 200; ++$count) {
$plural = $translator->getPluralizationRule($count, $langCode);
$matrix[$langCode][$count] = $plural;
}
}
return $matrix;
}
}

View File

@ -0,0 +1,31 @@
<?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\Contracts\Translation;
interface LocaleAwareInterface
{
/**
* Sets the current locale.
*
* @param string $locale The locale
*
* @throws \InvalidArgumentException If the locale contains invalid characters
*/
public function setLocale($locale);
/**
* Returns the current locale.
*
* @return string The locale
*/
public function getLocale();
}

View File

@ -0,0 +1,65 @@
<?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\Contracts\Translation;
/**
* @author Fabien Potencier <fabien@symfony.com>
*/
interface TranslatorInterface
{
/**
* Translates the given message.
*
* When a number is provided as a parameter named "%count%", the message is parsed for plural
* forms and a translation is chosen according to this number using the following rules:
*
* Given a message with different plural translations separated by a
* pipe (|), this method returns the correct portion of the message based
* on the given number, locale and the pluralization rules in the message
* itself.
*
* The message supports two different types of pluralization rules:
*
* interval: {0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples
* indexed: There is one apple|There are %count% apples
*
* The indexed solution can also contain labels (e.g. one: There is one apple).
* This is purely for making the translations more clear - it does not
* affect the functionality.
*
* The two methods can also be mixed:
* {0} There are no apples|one: There is one apple|more: There are %count% apples
*
* An interval can represent a finite set of numbers:
* {1,2,3,4}
*
* An interval can represent numbers between two numbers:
* [1, +Inf]
* ]-1,2[
*
* The left delimiter can be [ (inclusive) or ] (exclusive).
* The right delimiter can be [ (exclusive) or ] (inclusive).
* Beside numbers, you can use -Inf and +Inf for the infinite.
*
* @see https://en.wikipedia.org/wiki/ISO_31-11
*
* @param string $id The message id (may also be an object that can be cast to string)
* @param array $parameters An array of parameters for the message
* @param string|null $domain The domain for the message or null to use the default
* @param string|null $locale The locale or null to use the default
*
* @return string The translated string
*
* @throws \InvalidArgumentException If the locale contains invalid characters
*/
public function trans($id, array $parameters = array(), $domain = null, $locale = null);
}

View File

@ -0,0 +1,255 @@
<?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\Contracts\Translation;
use Symfony\Component\Translation\Exception\InvalidArgumentException;
/**
* A trait to help implement TranslatorInterface and LocaleAwareInterface.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
trait TranslatorTrait
{
private $locale;
/**
* {@inheritdoc}
*/
public function setLocale($locale)
{
$this->locale = (string) $locale;
}
/**
* {@inheritdoc}
*/
public function getLocale()
{
return $this->locale ?: \Locale::getDefault();
}
/**
* {@inheritdoc}
*/
public function trans($id, array $parameters = array(), $domain = null, $locale = null)
{
$id = (string) $id;
if (!isset($parameters['%count%']) || !is_numeric($parameters['%count%'])) {
return strtr($id, $parameters);
}
$number = (float) $parameters['%count%'];
$locale = (string) $locale ?: $this->getLocale();
$parts = array();
if (preg_match('/^\|++$/', $id)) {
$parts = explode('|', $id);
} elseif (preg_match_all('/(?:\|\||[^\|])++/', $id, $matches)) {
$parts = $matches[0];
}
$intervalRegexp = <<<'EOF'
/^(?P<interval>
({\s*
(\-?\d+(\.\d+)?[\s*,\s*\-?\d+(\.\d+)?]*)
\s*})
|
(?P<left_delimiter>[\[\]])
\s*
(?P<left>-Inf|\-?\d+(\.\d+)?)
\s*,\s*
(?P<right>\+?Inf|\-?\d+(\.\d+)?)
\s*
(?P<right_delimiter>[\[\]])
)\s*(?P<message>.*?)$/xs
EOF;
$standardRules = array();
foreach ($parts as $part) {
$part = trim(str_replace('||', '|', $part));
// try to match an explicit rule, then fallback to the standard ones
if (preg_match($intervalRegexp, $part, $matches)) {
if ($matches[2]) {
foreach (explode(',', $matches[3]) as $n) {
if ($number == $n) {
return strtr($matches['message'], $parameters);
}
}
} else {
$leftNumber = '-Inf' === $matches['left'] ? -INF : (float) $matches['left'];
$rightNumber = \is_numeric($matches['right']) ? (float) $matches['right'] : INF;
if (('[' === $matches['left_delimiter'] ? $number >= $leftNumber : $number > $leftNumber)
&& (']' === $matches['right_delimiter'] ? $number <= $rightNumber : $number < $rightNumber)
) {
return strtr($matches['message'], $parameters);
}
}
} elseif (preg_match('/^\w+\:\s*(.*?)$/', $part, $matches)) {
$standardRules[] = $matches[1];
} else {
$standardRules[] = $part;
}
}
$position = $this->getPluralizationRule($number, $locale);
if (!isset($standardRules[$position])) {
// when there's exactly one rule given, and that rule is a standard
// rule, use this rule
if (1 === \count($parts) && isset($standardRules[0])) {
return strtr($standardRules[0], $parameters);
}
$message = sprintf('Unable to choose a translation for "%s" with locale "%s" for value "%d". Double check that this translation has the correct plural options (e.g. "There is one apple|There are %%count%% apples").', $id, $locale, $number);
if (\class_exists(InvalidArgumentException::class)) {
throw new InvalidArgumentException($message);
}
throw new \InvalidArgumentException($message);
}
return strtr($standardRules[$position], $parameters);
}
/**
* Returns the plural position to use for the given locale and number.
*
* The plural rules are derived from code of the Zend Framework (2010-09-25),
* which is subject to the new BSD license (http://framework.zend.com/license/new-bsd).
* Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
*/
private function getPluralizationRule(int $number, string $locale): int
{
switch ('pt_BR' !== $locale && \strlen($locale) > 3 ? substr($locale, 0, strrpos($locale, '_')) : $locale) {
case 'af':
case 'bn':
case 'bg':
case 'ca':
case 'da':
case 'de':
case 'el':
case 'en':
case 'eo':
case 'es':
case 'et':
case 'eu':
case 'fa':
case 'fi':
case 'fo':
case 'fur':
case 'fy':
case 'gl':
case 'gu':
case 'ha':
case 'he':
case 'hu':
case 'is':
case 'it':
case 'ku':
case 'lb':
case 'ml':
case 'mn':
case 'mr':
case 'nah':
case 'nb':
case 'ne':
case 'nl':
case 'nn':
case 'no':
case 'oc':
case 'om':
case 'or':
case 'pa':
case 'pap':
case 'ps':
case 'pt':
case 'so':
case 'sq':
case 'sv':
case 'sw':
case 'ta':
case 'te':
case 'tk':
case 'ur':
case 'zu':
return (1 == $number) ? 0 : 1;
case 'am':
case 'bh':
case 'fil':
case 'fr':
case 'gun':
case 'hi':
case 'hy':
case 'ln':
case 'mg':
case 'nso':
case 'pt_BR':
case 'ti':
case 'wa':
return ((0 == $number) || (1 == $number)) ? 0 : 1;
case 'be':
case 'bs':
case 'hr':
case 'ru':
case 'sh':
case 'sr':
case 'uk':
return ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);
case 'cs':
case 'sk':
return (1 == $number) ? 0 : ((($number >= 2) && ($number <= 4)) ? 1 : 2);
case 'ga':
return (1 == $number) ? 0 : ((2 == $number) ? 1 : 2);
case 'lt':
return ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);
case 'sl':
return (1 == $number % 100) ? 0 : ((2 == $number % 100) ? 1 : (((3 == $number % 100) || (4 == $number % 100)) ? 2 : 3));
case 'mk':
return (1 == $number % 10) ? 0 : 1;
case 'mt':
return (1 == $number) ? 0 : (((0 == $number) || (($number % 100 > 1) && ($number % 100 < 11))) ? 1 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 2 : 3));
case 'lv':
return (0 == $number) ? 0 : (((1 == $number % 10) && (11 != $number % 100)) ? 1 : 2);
case 'pl':
return (1 == $number) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 1 : 2);
case 'cy':
return (1 == $number) ? 0 : ((2 == $number) ? 1 : (((8 == $number) || (11 == $number)) ? 2 : 3));
case 'ro':
return (1 == $number) ? 0 : (((0 == $number) || (($number % 100 > 0) && ($number % 100 < 20))) ? 1 : 2);
case 'ar':
return (0 == $number) ? 0 : ((1 == $number) ? 1 : ((2 == $number) ? 2 : ((($number % 100 >= 3) && ($number % 100 <= 10)) ? 3 : ((($number % 100 >= 11) && ($number % 100 <= 99)) ? 4 : 5))));
default:
return 0;
}
}
}

View File

@ -0,0 +1,44 @@
{
"name": "symfony/contracts",
"type": "library",
"description": "A set of abstractions extracted out of the Symfony components",
"keywords": ["abstractions", "contracts", "decoupling", "interfaces", "interoperability", "standards"],
"homepage": "https://symfony.com",
"license": "MIT",
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"require": {
"php": "^7.1.3"
},
"require-dev": {
"psr/cache": "^1.0",
"psr/container": "^1.0"
},
"suggest": {
"psr/cache": "When using the Cache contracts",
"psr/container": "When using the Service contracts",
"symfony/cache-contracts-implementation": "",
"symfony/service-contracts-implementation": "",
"symfony/translation-contracts-implementation": ""
},
"autoload": {
"psr-4": { "Symfony\\Contracts\\": "" },
"exclude-from-classmap": [
"**/Tests/"
]
},
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
}
}

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/5.2/phpunit.xsd"
backupGlobals="false"
colors="true"
bootstrap="vendor/autoload.php"
failOnRisky="true"
failOnWarning="true"
>
<php>
<ini name="error_reporting" value="-1" />
</php>
<testsuites>
<testsuite name="Symfony Contracts Test Suite">
<directory>./Tests/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>./</directory>
<exclude>
<directory>./Tests</directory>
<directory>./vendor</directory>
</exclude>
</whitelist>
</filter>
</phpunit>

View File

@ -0,0 +1,227 @@
<?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\Polyfill\Ctype;
/**
* Ctype implementation through regex.
*
* @internal
*
* @author Gert de Pagter <BackEndTea@gmail.com>
*/
final class Ctype
{
/**
* Returns TRUE if every character in text is either a letter or a digit, FALSE otherwise.
*
* @see https://php.net/ctype-alnum
*
* @param string|int $text
*
* @return bool
*/
public static function ctype_alnum($text)
{
$text = self::convert_int_to_char_for_ctype($text);
return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z0-9]/', $text);
}
/**
* Returns TRUE if every character in text is a letter, FALSE otherwise.
*
* @see https://php.net/ctype-alpha
*
* @param string|int $text
*
* @return bool
*/
public static function ctype_alpha($text)
{
$text = self::convert_int_to_char_for_ctype($text);
return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z]/', $text);
}
/**
* Returns TRUE if every character in text is a control character from the current locale, FALSE otherwise.
*
* @see https://php.net/ctype-cntrl
*
* @param string|int $text
*
* @return bool
*/
public static function ctype_cntrl($text)
{
$text = self::convert_int_to_char_for_ctype($text);
return \is_string($text) && '' !== $text && !preg_match('/[^\x00-\x1f\x7f]/', $text);
}
/**
* Returns TRUE if every character in the string text is a decimal digit, FALSE otherwise.
*
* @see https://php.net/ctype-digit
*
* @param string|int $text
*
* @return bool
*/
public static function ctype_digit($text)
{
$text = self::convert_int_to_char_for_ctype($text);
return \is_string($text) && '' !== $text && !preg_match('/[^0-9]/', $text);
}
/**
* Returns TRUE if every character in text is printable and actually creates visible output (no white space), FALSE otherwise.
*
* @see https://php.net/ctype-graph
*
* @param string|int $text
*
* @return bool
*/
public static function ctype_graph($text)
{
$text = self::convert_int_to_char_for_ctype($text);
return \is_string($text) && '' !== $text && !preg_match('/[^!-~]/', $text);
}
/**
* Returns TRUE if every character in text is a lowercase letter.
*
* @see https://php.net/ctype-lower
*
* @param string|int $text
*
* @return bool
*/
public static function ctype_lower($text)
{
$text = self::convert_int_to_char_for_ctype($text);
return \is_string($text) && '' !== $text && !preg_match('/[^a-z]/', $text);
}
/**
* Returns TRUE if every character in text will actually create output (including blanks). Returns FALSE if text contains control characters or characters that do not have any output or control function at all.
*
* @see https://php.net/ctype-print
*
* @param string|int $text
*
* @return bool
*/
public static function ctype_print($text)
{
$text = self::convert_int_to_char_for_ctype($text);
return \is_string($text) && '' !== $text && !preg_match('/[^ -~]/', $text);
}
/**
* Returns TRUE if every character in text is printable, but neither letter, digit or blank, FALSE otherwise.
*
* @see https://php.net/ctype-punct
*
* @param string|int $text
*
* @return bool
*/
public static function ctype_punct($text)
{
$text = self::convert_int_to_char_for_ctype($text);
return \is_string($text) && '' !== $text && !preg_match('/[^!-\/\:-@\[-`\{-~]/', $text);
}
/**
* Returns TRUE if every character in text creates some sort of white space, FALSE otherwise. Besides the blank character this also includes tab, vertical tab, line feed, carriage return and form feed characters.
*
* @see https://php.net/ctype-space
*
* @param string|int $text
*
* @return bool
*/
public static function ctype_space($text)
{
$text = self::convert_int_to_char_for_ctype($text);
return \is_string($text) && '' !== $text && !preg_match('/[^\s]/', $text);
}
/**
* Returns TRUE if every character in text is an uppercase letter.
*
* @see https://php.net/ctype-upper
*
* @param string|int $text
*
* @return bool
*/
public static function ctype_upper($text)
{
$text = self::convert_int_to_char_for_ctype($text);
return \is_string($text) && '' !== $text && !preg_match('/[^A-Z]/', $text);
}
/**
* Returns TRUE if every character in text is a hexadecimal 'digit', that is a decimal digit or a character from [A-Fa-f] , FALSE otherwise.
*
* @see https://php.net/ctype-xdigit
*
* @param string|int $text
*
* @return bool
*/
public static function ctype_xdigit($text)
{
$text = self::convert_int_to_char_for_ctype($text);
return \is_string($text) && '' !== $text && !preg_match('/[^A-Fa-f0-9]/', $text);
}
/**
* Converts integers to their char versions according to normal ctype behaviour, if needed.
*
* If an integer between -128 and 255 inclusive is provided,
* it is interpreted as the ASCII value of a single character
* (negative values have 256 added in order to allow characters in the Extended ASCII range).
* Any other integer is interpreted as a string containing the decimal digits of the integer.
*
* @param string|int $int
*
* @return mixed
*/
private static function convert_int_to_char_for_ctype($int)
{
if (!\is_int($int)) {
return $int;
}
if ($int < -128 || $int > 255) {
return (string) $int;
}
if ($int < 0) {
$int += 256;
}
return \chr($int);
}
}

View File

@ -0,0 +1,19 @@
Copyright (c) 2018-2019 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -0,0 +1,12 @@
Symfony Polyfill / Ctype
========================
This component provides `ctype_*` functions to users who run php versions without the ctype extension.
More information can be found in the
[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).
License
=======
This library is released under the [MIT license](LICENSE).

View File

@ -0,0 +1,26 @@
<?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.
*/
use Symfony\Polyfill\Ctype as p;
if (!function_exists('ctype_alnum')) {
function ctype_alnum($text) { return p\Ctype::ctype_alnum($text); }
function ctype_alpha($text) { return p\Ctype::ctype_alpha($text); }
function ctype_cntrl($text) { return p\Ctype::ctype_cntrl($text); }
function ctype_digit($text) { return p\Ctype::ctype_digit($text); }
function ctype_graph($text) { return p\Ctype::ctype_graph($text); }
function ctype_lower($text) { return p\Ctype::ctype_lower($text); }
function ctype_print($text) { return p\Ctype::ctype_print($text); }
function ctype_punct($text) { return p\Ctype::ctype_punct($text); }
function ctype_space($text) { return p\Ctype::ctype_space($text); }
function ctype_upper($text) { return p\Ctype::ctype_upper($text); }
function ctype_xdigit($text) { return p\Ctype::ctype_xdigit($text); }
}

View File

@ -0,0 +1,34 @@
{
"name": "symfony/polyfill-ctype",
"type": "library",
"description": "Symfony polyfill for ctype functions",
"keywords": ["polyfill", "compatibility", "portable", "ctype"],
"homepage": "https://symfony.com",
"license": "MIT",
"authors": [
{
"name": "Gert de Pagter",
"email": "BackEndTea@gmail.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"require": {
"php": ">=5.3.3"
},
"autoload": {
"psr-4": { "Symfony\\Polyfill\\Ctype\\": "" },
"files": [ "bootstrap.php" ]
},
"suggest": {
"ext-ctype": "For best performance"
},
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "1.11-dev"
}
}
}

View File

@ -0,0 +1,19 @@
Copyright (c) 2015-2019 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -0,0 +1,23 @@
Symfony Polyfill / Intl: ICU
============================
This component provides a collection of functions/classes using the
[`symfony/intl`](https://github.com/symfony/intl) package when the
[Intl](http://php.net/intl) extension is not installed, including:
- [`intl_is_failure()`](http://php.net/manual/en/function.intl-is-failure.php)
- [`intl_get_error_code()`](http://php.net/manual/en/function.intl-get-error-code.php)
- [`intl_get_error_message()`](http://php.net/manual/en/function.intl-get-error-message.php)
- [`intl_error_name()`](http://php.net/manual/en/function.intl-error-name.php)
- [`Collator`](http://php.net/Collator)
- [`NumberFormatter`](http://php.net/NumberFormatter)
- [`Locale`](http://php.net/Locale)
- [`IntlDateFormatter`](http://php.net/IntlDateFormatter)
More information can be found in the
[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).
License
=======
This library is released under the [MIT license](LICENSE).

View File

@ -0,0 +1,19 @@
<?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.
*/
use Symfony\Component\Intl\Globals\IntlGlobals;
if (!function_exists('intl_is_failure')) {
function intl_is_failure($errorCode) { return IntlGlobals::isFailure($errorCode); }
function intl_get_error_code() { return IntlGlobals::getErrorCode(); }
function intl_get_error_message() { return IntlGlobals::getErrorMessage(); }
function intl_error_name($errorCode) { return IntlGlobals::getErrorName($errorCode); }
}

View File

@ -0,0 +1,34 @@
{
"name": "symfony/polyfill-intl-icu",
"type": "library",
"description": "Symfony polyfill for intl's ICU-related data and classes",
"keywords": ["polyfill", "shim", "compatibility", "portable", "intl", "icu"],
"homepage": "https://symfony.com",
"license": "MIT",
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"require": {
"php": ">=5.3.3",
"symfony/intl": "~2.3|~3.0|~4.0"
},
"autoload": {
"files": [ "bootstrap.php" ]
},
"suggest": {
"ext-intl": "For best performance"
},
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "1.9-dev"
}
}
}

View File

@ -0,0 +1,19 @@
Copyright (c) 2015-2019 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -0,0 +1,800 @@
<?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\Polyfill\Mbstring;
/**
* Partial mbstring implementation in PHP, iconv based, UTF-8 centric.
*
* Implemented:
* - mb_chr - Returns a specific character from its Unicode code point
* - mb_convert_encoding - Convert character encoding
* - mb_convert_variables - Convert character code in variable(s)
* - mb_decode_mimeheader - Decode string in MIME header field
* - mb_encode_mimeheader - Encode string for MIME header XXX NATIVE IMPLEMENTATION IS REALLY BUGGED
* - mb_decode_numericentity - Decode HTML numeric string reference to character
* - mb_encode_numericentity - Encode character to HTML numeric string reference
* - mb_convert_case - Perform case folding on a string
* - mb_detect_encoding - Detect character encoding
* - mb_get_info - Get internal settings of mbstring
* - mb_http_input - Detect HTTP input character encoding
* - mb_http_output - Set/Get HTTP output character encoding
* - mb_internal_encoding - Set/Get internal character encoding
* - mb_list_encodings - Returns an array of all supported encodings
* - mb_ord - Returns the Unicode code point of a character
* - mb_output_handler - Callback function converts character encoding in output buffer
* - mb_scrub - Replaces ill-formed byte sequences with substitute characters
* - mb_strlen - Get string length
* - mb_strpos - Find position of first occurrence of string in a string
* - mb_strrpos - Find position of last occurrence of a string in a string
* - mb_strtolower - Make a string lowercase
* - mb_strtoupper - Make a string uppercase
* - mb_substitute_character - Set/Get substitution character
* - mb_substr - Get part of string
* - mb_stripos - Finds position of first occurrence of a string within another, case insensitive
* - mb_stristr - Finds first occurrence of a string within another, case insensitive
* - mb_strrchr - Finds the last occurrence of a character in a string within another
* - mb_strrichr - Finds the last occurrence of a character in a string within another, case insensitive
* - mb_strripos - Finds position of last occurrence of a string within another, case insensitive
* - mb_strstr - Finds first occurrence of a string within another
* - mb_strwidth - Return width of string
* - mb_substr_count - Count the number of substring occurrences
*
* Not implemented:
* - mb_convert_kana - Convert "kana" one from another ("zen-kaku", "han-kaku" and more)
* - mb_ereg_* - Regular expression with multibyte support
* - mb_parse_str - Parse GET/POST/COOKIE data and set global variable
* - mb_preferred_mime_name - Get MIME charset string
* - mb_regex_encoding - Returns current encoding for multibyte regex as string
* - mb_regex_set_options - Set/Get the default options for mbregex functions
* - mb_send_mail - Send encoded mail
* - mb_split - Split multibyte string using regular expression
* - mb_strcut - Get part of string
* - mb_strimwidth - Get truncated string with specified width
*
* @author Nicolas Grekas <p@tchwork.com>
*
* @internal
*/
final class Mbstring
{
const MB_CASE_FOLD = PHP_INT_MAX;
private static $encodingList = array('ASCII', 'UTF-8');
private static $language = 'neutral';
private static $internalEncoding = 'UTF-8';
private static $caseFold = array(
array('µ', 'ſ', "\xCD\x85", 'ς', "\xCF\x90", "\xCF\x91", "\xCF\x95", "\xCF\x96", "\xCF\xB0", "\xCF\xB1", "\xCF\xB5", "\xE1\xBA\x9B", "\xE1\xBE\xBE"),
array('μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "\xE1\xB9\xA1", 'ι'),
);
public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null)
{
if (\is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) {
$fromEncoding = self::mb_detect_encoding($s, $fromEncoding);
} else {
$fromEncoding = self::getEncoding($fromEncoding);
}
$toEncoding = self::getEncoding($toEncoding);
if ('BASE64' === $fromEncoding) {
$s = base64_decode($s);
$fromEncoding = $toEncoding;
}
if ('BASE64' === $toEncoding) {
return base64_encode($s);
}
if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) {
if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) {
$fromEncoding = 'Windows-1252';
}
if ('UTF-8' !== $fromEncoding) {
$s = iconv($fromEncoding, 'UTF-8//IGNORE', $s);
}
return preg_replace_callback('/[\x80-\xFF]+/', array(__CLASS__, 'html_encoding_callback'), $s);
}
if ('HTML-ENTITIES' === $fromEncoding) {
$s = html_entity_decode($s, ENT_COMPAT, 'UTF-8');
$fromEncoding = 'UTF-8';
}
return iconv($fromEncoding, $toEncoding.'//IGNORE', $s);
}
public static function mb_convert_variables($toEncoding, $fromEncoding, &$a = null, &$b = null, &$c = null, &$d = null, &$e = null, &$f = null)
{
$vars = array(&$a, &$b, &$c, &$d, &$e, &$f);
$ok = true;
array_walk_recursive($vars, function (&$v) use (&$ok, $toEncoding, $fromEncoding) {
if (false === $v = Mbstring::mb_convert_encoding($v, $toEncoding, $fromEncoding)) {
$ok = false;
}
});
return $ok ? $fromEncoding : false;
}
public static function mb_decode_mimeheader($s)
{
return iconv_mime_decode($s, 2, self::$internalEncoding);
}
public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null)
{
trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', E_USER_WARNING);
}
public static function mb_decode_numericentity($s, $convmap, $encoding = null)
{
if (null !== $s && !\is_scalar($s) && !(\is_object($s) && \method_exists($s, '__toString'))) {
trigger_error('mb_decode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', E_USER_WARNING);
return null;
}
if (!\is_array($convmap) || !$convmap) {
return false;
}
if (null !== $encoding && !\is_scalar($encoding)) {
trigger_error('mb_decode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', E_USER_WARNING);
return ''; // Instead of null (cf. mb_encode_numericentity).
}
$s = (string) $s;
if ('' === $s) {
return '';
}
$encoding = self::getEncoding($encoding);
if ('UTF-8' === $encoding) {
$encoding = null;
if (!preg_match('//u', $s)) {
$s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
}
} else {
$s = iconv($encoding, 'UTF-8//IGNORE', $s);
}
$cnt = floor(\count($convmap) / 4) * 4;
for ($i = 0; $i < $cnt; $i += 4) {
// collector_decode_htmlnumericentity ignores $convmap[$i + 3]
$convmap[$i] += $convmap[$i + 2];
$convmap[$i + 1] += $convmap[$i + 2];
}
$s = preg_replace_callback('/&#(?:0*([0-9]+)|x0*([0-9a-fA-F]+))(?!&);?/', function (array $m) use ($cnt, $convmap) {
$c = isset($m[2]) ? (int) hexdec($m[2]) : $m[1];
for ($i = 0; $i < $cnt; $i += 4) {
if ($c >= $convmap[$i] && $c <= $convmap[$i + 1]) {
return Mbstring::mb_chr($c - $convmap[$i + 2]);
}
}
return $m[0];
}, $s);
if (null === $encoding) {
return $s;
}
return iconv('UTF-8', $encoding.'//IGNORE', $s);
}
public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = false)
{
if (null !== $s && !\is_scalar($s) && !(\is_object($s) && \method_exists($s, '__toString'))) {
trigger_error('mb_encode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', E_USER_WARNING);
return null;
}
if (!\is_array($convmap) || !$convmap) {
return false;
}
if (null !== $encoding && !\is_scalar($encoding)) {
trigger_error('mb_encode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', E_USER_WARNING);
return null; // Instead of '' (cf. mb_decode_numericentity).
}
if (null !== $is_hex && !\is_scalar($is_hex)) {
trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, '.\gettype($s).' given', E_USER_WARNING);
return null;
}
$s = (string) $s;
if ('' === $s) {
return '';
}
$encoding = self::getEncoding($encoding);
if ('UTF-8' === $encoding) {
$encoding = null;
if (!preg_match('//u', $s)) {
$s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
}
} else {
$s = iconv($encoding, 'UTF-8//IGNORE', $s);
}
static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4);
$cnt = floor(\count($convmap) / 4) * 4;
$i = 0;
$len = \strlen($s);
$result = '';
while ($i < $len) {
$ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
$uchr = substr($s, $i, $ulen);
$i += $ulen;
$c = self::mb_ord($uchr);
for ($j = 0; $j < $cnt; $j += 4) {
if ($c >= $convmap[$j] && $c <= $convmap[$j + 1]) {
$cOffset = ($c + $convmap[$j + 2]) & $convmap[$j + 3];
$result .= $is_hex ? sprintf('&#x%X;', $cOffset) : '&#'.$cOffset.';';
continue 2;
}
}
$result .= $uchr;
}
if (null === $encoding) {
return $result;
}
return iconv('UTF-8', $encoding.'//IGNORE', $result);
}
public static function mb_convert_case($s, $mode, $encoding = null)
{
$s = (string) $s;
if ('' === $s) {
return '';
}
$encoding = self::getEncoding($encoding);
if ('UTF-8' === $encoding) {
$encoding = null;
if (!preg_match('//u', $s)) {
$s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
}
} else {
$s = iconv($encoding, 'UTF-8//IGNORE', $s);
}
if (MB_CASE_TITLE == $mode) {
static $titleRegexp = null;
if (null === $titleRegexp) {
$titleRegexp = self::getData('titleCaseRegexp');
}
$s = preg_replace_callback($titleRegexp, array(__CLASS__, 'title_case'), $s);
} else {
if (MB_CASE_UPPER == $mode) {
static $upper = null;
if (null === $upper) {
$upper = self::getData('upperCase');
}
$map = $upper;
} else {
if (self::MB_CASE_FOLD === $mode) {
$s = str_replace(self::$caseFold[0], self::$caseFold[1], $s);
}
static $lower = null;
if (null === $lower) {
$lower = self::getData('lowerCase');
}
$map = $lower;
}
static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4);
$i = 0;
$len = \strlen($s);
while ($i < $len) {
$ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
$uchr = substr($s, $i, $ulen);
$i += $ulen;
if (isset($map[$uchr])) {
$uchr = $map[$uchr];
$nlen = \strlen($uchr);
if ($nlen == $ulen) {
$nlen = $i;
do {
$s[--$nlen] = $uchr[--$ulen];
} while ($ulen);
} else {
$s = substr_replace($s, $uchr, $i - $ulen, $ulen);
$len += $nlen - $ulen;
$i += $nlen - $ulen;
}
}
}
}
if (null === $encoding) {
return $s;
}
return iconv('UTF-8', $encoding.'//IGNORE', $s);
}
public static function mb_internal_encoding($encoding = null)
{
if (null === $encoding) {
return self::$internalEncoding;
}
$encoding = self::getEncoding($encoding);
if ('UTF-8' === $encoding || false !== @iconv($encoding, $encoding, ' ')) {
self::$internalEncoding = $encoding;
return true;
}
return false;
}
public static function mb_language($lang = null)
{
if (null === $lang) {
return self::$language;
}
switch ($lang = strtolower($lang)) {
case 'uni':
case 'neutral':
self::$language = $lang;
return true;
}
return false;
}
public static function mb_list_encodings()
{
return array('UTF-8');
}
public static function mb_encoding_aliases($encoding)
{
switch (strtoupper($encoding)) {
case 'UTF8':
case 'UTF-8':
return array('utf8');
}
return false;
}
public static function mb_check_encoding($var = null, $encoding = null)
{
if (null === $encoding) {
if (null === $var) {
return false;
}
$encoding = self::$internalEncoding;
}
return self::mb_detect_encoding($var, array($encoding)) || false !== @iconv($encoding, $encoding, $var);
}
public static function mb_detect_encoding($str, $encodingList = null, $strict = false)
{
if (null === $encodingList) {
$encodingList = self::$encodingList;
} else {
if (!\is_array($encodingList)) {
$encodingList = array_map('trim', explode(',', $encodingList));
}
$encodingList = array_map('strtoupper', $encodingList);
}
foreach ($encodingList as $enc) {
switch ($enc) {
case 'ASCII':
if (!preg_match('/[\x80-\xFF]/', $str)) {
return $enc;
}
break;
case 'UTF8':
case 'UTF-8':
if (preg_match('//u', $str)) {
return 'UTF-8';
}
break;
default:
if (0 === strncmp($enc, 'ISO-8859-', 9)) {
return $enc;
}
}
}
return false;
}
public static function mb_detect_order($encodingList = null)
{
if (null === $encodingList) {
return self::$encodingList;
}
if (!\is_array($encodingList)) {
$encodingList = array_map('trim', explode(',', $encodingList));
}
$encodingList = array_map('strtoupper', $encodingList);
foreach ($encodingList as $enc) {
switch ($enc) {
default:
if (strncmp($enc, 'ISO-8859-', 9)) {
return false;
}
// no break
case 'ASCII':
case 'UTF8':
case 'UTF-8':
}
}
self::$encodingList = $encodingList;
return true;
}
public static function mb_strlen($s, $encoding = null)
{
$encoding = self::getEncoding($encoding);
if ('CP850' === $encoding || 'ASCII' === $encoding) {
return \strlen($s);
}
return @iconv_strlen($s, $encoding);
}
public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null)
{
$encoding = self::getEncoding($encoding);
if ('CP850' === $encoding || 'ASCII' === $encoding) {
return strpos($haystack, $needle, $offset);
}
$needle = (string) $needle;
if ('' === $needle) {
trigger_error(__METHOD__.': Empty delimiter', E_USER_WARNING);
return false;
}
return iconv_strpos($haystack, $needle, $offset, $encoding);
}
public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null)
{
$encoding = self::getEncoding($encoding);
if ('CP850' === $encoding || 'ASCII' === $encoding) {
return strrpos($haystack, $needle, $offset);
}
if ($offset != (int) $offset) {
$offset = 0;
} elseif ($offset = (int) $offset) {
if ($offset < 0) {
$haystack = self::mb_substr($haystack, 0, $offset, $encoding);
$offset = 0;
} else {
$haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding);
}
}
$pos = iconv_strrpos($haystack, $needle, $encoding);
return false !== $pos ? $offset + $pos : false;
}
public static function mb_strtolower($s, $encoding = null)
{
return self::mb_convert_case($s, MB_CASE_LOWER, $encoding);
}
public static function mb_strtoupper($s, $encoding = null)
{
return self::mb_convert_case($s, MB_CASE_UPPER, $encoding);
}
public static function mb_substitute_character($c = null)
{
if (0 === strcasecmp($c, 'none')) {
return true;
}
return null !== $c ? false : 'none';
}
public static function mb_substr($s, $start, $length = null, $encoding = null)
{
$encoding = self::getEncoding($encoding);
if ('CP850' === $encoding || 'ASCII' === $encoding) {
return substr($s, $start, null === $length ? 2147483647 : $length);
}
if ($start < 0) {
$start = iconv_strlen($s, $encoding) + $start;
if ($start < 0) {
$start = 0;
}
}
if (null === $length) {
$length = 2147483647;
} elseif ($length < 0) {
$length = iconv_strlen($s, $encoding) + $length - $start;
if ($length < 0) {
return '';
}
}
return (string) iconv_substr($s, $start, $length, $encoding);
}
public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null)
{
$haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
$needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
return self::mb_strpos($haystack, $needle, $offset, $encoding);
}
public static function mb_stristr($haystack, $needle, $part = false, $encoding = null)
{
$pos = self::mb_stripos($haystack, $needle, 0, $encoding);
return self::getSubpart($pos, $part, $haystack, $encoding);
}
public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null)
{
$encoding = self::getEncoding($encoding);
if ('CP850' === $encoding || 'ASCII' === $encoding) {
return strrchr($haystack, $needle, $part);
}
$needle = self::mb_substr($needle, 0, 1, $encoding);
$pos = iconv_strrpos($haystack, $needle, $encoding);
return self::getSubpart($pos, $part, $haystack, $encoding);
}
public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null)
{
$needle = self::mb_substr($needle, 0, 1, $encoding);
$pos = self::mb_strripos($haystack, $needle, $encoding);
return self::getSubpart($pos, $part, $haystack, $encoding);
}
public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null)
{
$haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
$needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
return self::mb_strrpos($haystack, $needle, $offset, $encoding);
}
public static function mb_strstr($haystack, $needle, $part = false, $encoding = null)
{
$pos = strpos($haystack, $needle);
if (false === $pos) {
return false;
}
if ($part) {
return substr($haystack, 0, $pos);
}
return substr($haystack, $pos);
}
public static function mb_get_info($type = 'all')
{
$info = array(
'internal_encoding' => self::$internalEncoding,
'http_output' => 'pass',
'http_output_conv_mimetypes' => '^(text/|application/xhtml\+xml)',
'func_overload' => 0,
'func_overload_list' => 'no overload',
'mail_charset' => 'UTF-8',
'mail_header_encoding' => 'BASE64',
'mail_body_encoding' => 'BASE64',
'illegal_chars' => 0,
'encoding_translation' => 'Off',
'language' => self::$language,
'detect_order' => self::$encodingList,
'substitute_character' => 'none',
'strict_detection' => 'Off',
);
if ('all' === $type) {
return $info;
}
if (isset($info[$type])) {
return $info[$type];
}
return false;
}
public static function mb_http_input($type = '')
{
return false;
}
public static function mb_http_output($encoding = null)
{
return null !== $encoding ? 'pass' === $encoding : 'pass';
}
public static function mb_strwidth($s, $encoding = null)
{
$encoding = self::getEncoding($encoding);
if ('UTF-8' !== $encoding) {
$s = iconv($encoding, 'UTF-8//IGNORE', $s);
}
$s = preg_replace('/[\x{1100}-\x{115F}\x{2329}\x{232A}\x{2E80}-\x{303E}\x{3040}-\x{A4CF}\x{AC00}-\x{D7A3}\x{F900}-\x{FAFF}\x{FE10}-\x{FE19}\x{FE30}-\x{FE6F}\x{FF00}-\x{FF60}\x{FFE0}-\x{FFE6}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}]/u', '', $s, -1, $wide);
return ($wide << 1) + iconv_strlen($s, 'UTF-8');
}
public static function mb_substr_count($haystack, $needle, $encoding = null)
{
return substr_count($haystack, $needle);
}
public static function mb_output_handler($contents, $status)
{
return $contents;
}
public static function mb_chr($code, $encoding = null)
{
if (0x80 > $code %= 0x200000) {
$s = \chr($code);
} elseif (0x800 > $code) {
$s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F);
} elseif (0x10000 > $code) {
$s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
} else {
$s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
}
if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
$s = mb_convert_encoding($s, $encoding, 'UTF-8');
}
return $s;
}
public static function mb_ord($s, $encoding = null)
{
if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
$s = mb_convert_encoding($s, 'UTF-8', $encoding);
}
if (1 === \strlen($s)) {
return \ord($s);
}
$code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0;
if (0xF0 <= $code) {
return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80;
}
if (0xE0 <= $code) {
return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80;
}
if (0xC0 <= $code) {
return (($code - 0xC0) << 6) + $s[2] - 0x80;
}
return $code;
}
private static function getSubpart($pos, $part, $haystack, $encoding)
{
if (false === $pos) {
return false;
}
if ($part) {
return self::mb_substr($haystack, 0, $pos, $encoding);
}
return self::mb_substr($haystack, $pos, null, $encoding);
}
private static function html_encoding_callback(array $m)
{
$i = 1;
$entities = '';
$m = unpack('C*', htmlentities($m[0], ENT_COMPAT, 'UTF-8'));
while (isset($m[$i])) {
if (0x80 > $m[$i]) {
$entities .= \chr($m[$i++]);
continue;
}
if (0xF0 <= $m[$i]) {
$c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
} elseif (0xE0 <= $m[$i]) {
$c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
} else {
$c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80;
}
$entities .= '&#'.$c.';';
}
return $entities;
}
private static function title_case(array $s)
{
return self::mb_convert_case($s[1], MB_CASE_UPPER, 'UTF-8').self::mb_convert_case($s[2], MB_CASE_LOWER, 'UTF-8');
}
private static function getData($file)
{
if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) {
return require $file;
}
return false;
}
private static function getEncoding($encoding)
{
if (null === $encoding) {
return self::$internalEncoding;
}
$encoding = strtoupper($encoding);
if ('8BIT' === $encoding || 'BINARY' === $encoding) {
return 'CP850';
}
if ('UTF8' === $encoding) {
return 'UTF-8';
}
return $encoding;
}
}

View File

@ -0,0 +1,13 @@
Symfony Polyfill / Mbstring
===========================
This component provides a partial, native PHP implementation for the
[Mbstring](http://php.net/mbstring) extension.
More information can be found in the
[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).
License
=======
This library is released under the [MIT license](LICENSE).

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,58 @@
<?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.
*/
use Symfony\Polyfill\Mbstring as p;
if (!function_exists('mb_strlen')) {
define('MB_CASE_UPPER', 0);
define('MB_CASE_LOWER', 1);
define('MB_CASE_TITLE', 2);
function mb_convert_encoding($s, $to, $from = null) { return p\Mbstring::mb_convert_encoding($s, $to, $from); }
function mb_decode_mimeheader($s) { return p\Mbstring::mb_decode_mimeheader($s); }
function mb_encode_mimeheader($s, $charset = null, $transferEnc = null, $lf = null, $indent = null) { return p\Mbstring::mb_encode_mimeheader($s, $charset, $transferEnc, $lf, $indent); }
function mb_decode_numericentity($s, $convmap, $enc = null) { return p\Mbstring::mb_decode_numericentity($s, $convmap, $enc); }
function mb_encode_numericentity($s, $convmap, $enc = null, $is_hex = false) { return p\Mbstring::mb_encode_numericentity($s, $convmap, $enc, $is_hex); }
function mb_convert_case($s, $mode, $enc = null) { return p\Mbstring::mb_convert_case($s, $mode, $enc); }
function mb_internal_encoding($enc = null) { return p\Mbstring::mb_internal_encoding($enc); }
function mb_language($lang = null) { return p\Mbstring::mb_language($lang); }
function mb_list_encodings() { return p\Mbstring::mb_list_encodings(); }
function mb_encoding_aliases($encoding) { return p\Mbstring::mb_encoding_aliases($encoding); }
function mb_check_encoding($var = null, $encoding = null) { return p\Mbstring::mb_check_encoding($var, $encoding); }
function mb_detect_encoding($str, $encodingList = null, $strict = false) { return p\Mbstring::mb_detect_encoding($str, $encodingList, $strict); }
function mb_detect_order($encodingList = null) { return p\Mbstring::mb_detect_order($encodingList); }
function mb_parse_str($s, &$result = array()) { parse_str($s, $result); }
function mb_strlen($s, $enc = null) { return p\Mbstring::mb_strlen($s, $enc); }
function mb_strpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strpos($s, $needle, $offset, $enc); }
function mb_strtolower($s, $enc = null) { return p\Mbstring::mb_strtolower($s, $enc); }
function mb_strtoupper($s, $enc = null) { return p\Mbstring::mb_strtoupper($s, $enc); }
function mb_substitute_character($char = null) { return p\Mbstring::mb_substitute_character($char); }
function mb_substr($s, $start, $length = 2147483647, $enc = null) { return p\Mbstring::mb_substr($s, $start, $length, $enc); }
function mb_stripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_stripos($s, $needle, $offset, $enc); }
function mb_stristr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_stristr($s, $needle, $part, $enc); }
function mb_strrchr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrchr($s, $needle, $part, $enc); }
function mb_strrichr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrichr($s, $needle, $part, $enc); }
function mb_strripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strripos($s, $needle, $offset, $enc); }
function mb_strrpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strrpos($s, $needle, $offset, $enc); }
function mb_strstr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strstr($s, $needle, $part, $enc); }
function mb_get_info($type = 'all') { return p\Mbstring::mb_get_info($type); }
function mb_http_output($enc = null) { return p\Mbstring::mb_http_output($enc); }
function mb_strwidth($s, $enc = null) { return p\Mbstring::mb_strwidth($s, $enc); }
function mb_substr_count($haystack, $needle, $enc = null) { return p\Mbstring::mb_substr_count($haystack, $needle, $enc); }
function mb_output_handler($contents, $status) { return p\Mbstring::mb_output_handler($contents, $status); }
function mb_http_input($type = '') { return p\Mbstring::mb_http_input($type); }
function mb_convert_variables($toEncoding, $fromEncoding, &$a = null, &$b = null, &$c = null, &$d = null, &$e = null, &$f = null) { return p\Mbstring::mb_convert_variables($toEncoding, $fromEncoding, $a, $b, $c, $d, $e, $f); }
}
if (!function_exists('mb_chr')) {
function mb_ord($s, $enc = null) { return p\Mbstring::mb_ord($s, $enc); }
function mb_chr($code, $enc = null) { return p\Mbstring::mb_chr($code, $enc); }
function mb_scrub($s, $enc = null) { $enc = null === $enc ? mb_internal_encoding() : $enc; return mb_convert_encoding($s, $enc, $enc); }
}

View File

@ -0,0 +1,34 @@
{
"name": "symfony/polyfill-mbstring",
"type": "library",
"description": "Symfony polyfill for the Mbstring extension",
"keywords": ["polyfill", "shim", "compatibility", "portable", "mbstring"],
"homepage": "https://symfony.com",
"license": "MIT",
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"require": {
"php": ">=5.3.3"
},
"autoload": {
"psr-4": { "Symfony\\Polyfill\\Mbstring\\": "" },
"files": [ "bootstrap.php" ]
},
"suggest": {
"ext-mbstring": "For best performance"
},
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "1.11-dev"
}
}
}

View File

@ -0,0 +1,19 @@
Copyright (c) 2015-2019 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -0,0 +1,216 @@
<?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\Polyfill\Php72;
/**
* @author Nicolas Grekas <p@tchwork.com>
* @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
*
* @internal
*/
final class Php72
{
private static $hashMask;
public static function utf8_encode($s)
{
$s .= $s;
$len = \strlen($s);
for ($i = $len >> 1, $j = 0; $i < $len; ++$i, ++$j) {
switch (true) {
case $s[$i] < "\x80": $s[$j] = $s[$i]; break;
case $s[$i] < "\xC0": $s[$j] = "\xC2"; $s[++$j] = $s[$i]; break;
default: $s[$j] = "\xC3"; $s[++$j] = \chr(\ord($s[$i]) - 64); break;
}
}
return substr($s, 0, $j);
}
public static function utf8_decode($s)
{
$s = (string) $s;
$len = \strlen($s);
for ($i = 0, $j = 0; $i < $len; ++$i, ++$j) {
switch ($s[$i] & "\xF0") {
case "\xC0":
case "\xD0":
$c = (\ord($s[$i] & "\x1F") << 6) | \ord($s[++$i] & "\x3F");
$s[$j] = $c < 256 ? \chr($c) : '?';
break;
case "\xF0":
++$i;
// no break
case "\xE0":
$s[$j] = '?';
$i += 2;
break;
default:
$s[$j] = $s[$i];
}
}
return substr($s, 0, $j);
}
public static function php_os_family()
{
if ('\\' === \DIRECTORY_SEPARATOR) {
return 'Windows';
}
$map = array(
'Darwin' => 'Darwin',
'DragonFly' => 'BSD',
'FreeBSD' => 'BSD',
'NetBSD' => 'BSD',
'OpenBSD' => 'BSD',
'Linux' => 'Linux',
'SunOS' => 'Solaris',
);
return isset($map[PHP_OS]) ? $map[PHP_OS] : 'Unknown';
}
public static function spl_object_id($object)
{
if (null === self::$hashMask) {
self::initHashMask();
}
if (null === $hash = spl_object_hash($object)) {
return;
}
return self::$hashMask ^ hexdec(substr($hash, 16 - \PHP_INT_SIZE, \PHP_INT_SIZE));
}
public static function sapi_windows_vt100_support($stream, $enable = null)
{
if (!\is_resource($stream)) {
trigger_error('sapi_windows_vt100_support() expects parameter 1 to be resource, '.\gettype($stream).' given', E_USER_WARNING);
return false;
}
$meta = stream_get_meta_data($stream);
if ('STDIO' !== $meta['stream_type']) {
trigger_error('sapi_windows_vt100_support() was not able to analyze the specified stream', E_USER_WARNING);
return false;
}
// We cannot actually disable vt100 support if it is set
if (false === $enable || !self::stream_isatty($stream)) {
return false;
}
// The native function does not apply to stdin
$meta = array_map('strtolower', $meta);
$stdin = 'php://stdin' === $meta['uri'] || 'php://fd/0' === $meta['uri'];
return !$stdin
&& (false !== getenv('ANSICON')
|| 'ON' === getenv('ConEmuANSI')
|| 'xterm' === getenv('TERM')
|| 'Hyper' === getenv('TERM_PROGRAM'));
}
public static function stream_isatty($stream)
{
if (!\is_resource($stream)) {
trigger_error('stream_isatty() expects parameter 1 to be resource, '.\gettype($stream).' given', E_USER_WARNING);
return false;
}
if ('\\' === \DIRECTORY_SEPARATOR) {
$stat = @fstat($stream);
// Check if formatted mode is S_IFCHR
return $stat ? 0020000 === ($stat['mode'] & 0170000) : false;
}
return \function_exists('posix_isatty') && @posix_isatty($stream);
}
private static function initHashMask()
{
$obj = (object) array();
self::$hashMask = -1;
// check if we are nested in an output buffering handler to prevent a fatal error with ob_start() below
$obFuncs = array('ob_clean', 'ob_end_clean', 'ob_flush', 'ob_end_flush', 'ob_get_contents', 'ob_get_flush');
foreach (debug_backtrace(\PHP_VERSION_ID >= 50400 ? DEBUG_BACKTRACE_IGNORE_ARGS : false) as $frame) {
if (isset($frame['function'][0]) && !isset($frame['class']) && 'o' === $frame['function'][0] && \in_array($frame['function'], $obFuncs)) {
$frame['line'] = 0;
break;
}
}
if (!empty($frame['line'])) {
ob_start();
debug_zval_dump($obj);
self::$hashMask = (int) substr(ob_get_clean(), 17);
}
self::$hashMask ^= hexdec(substr(spl_object_hash($obj), 16 - \PHP_INT_SIZE, \PHP_INT_SIZE));
}
public static function mb_chr($code, $encoding = null)
{
if (0x80 > $code %= 0x200000) {
$s = \chr($code);
} elseif (0x800 > $code) {
$s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F);
} elseif (0x10000 > $code) {
$s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
} else {
$s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
}
if ('UTF-8' !== $encoding) {
$s = mb_convert_encoding($s, $encoding, 'UTF-8');
}
return $s;
}
public static function mb_ord($s, $encoding = null)
{
if (null == $encoding) {
$s = mb_convert_encoding($s, 'UTF-8');
} elseif ('UTF-8' !== $encoding) {
$s = mb_convert_encoding($s, 'UTF-8', $encoding);
}
if (1 === \strlen($s)) {
return \ord($s);
}
$code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0;
if (0xF0 <= $code) {
return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80;
}
if (0xE0 <= $code) {
return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80;
}
if (0xC0 <= $code) {
return (($code - 0xC0) << 6) + $s[2] - 0x80;
}
return $code;
}
}

View File

@ -0,0 +1,27 @@
Symfony Polyfill / Php72
========================
This component provides functions added to PHP 7.2 core:
- [`spl_object_id`](https://php.net/spl_object_id)
- [`stream_isatty`](https://php.net/stream_isatty)
On Windows only:
- [`sapi_windows_vt100_support`](https://php.net/sapi_windows_vt100_support)
Moved to core since 7.2 (was in the optional XML extension earlier):
- [`utf8_encode`](https://php.net/utf8_encode)
- [`utf8_decode`](https://php.net/utf8_decode)
Also, it provides a constant added to PHP 7.2:
- [`PHP_OS_FAMILY`](http://php.net/manual/en/reserved.constants.php#constant.php-os-family)
More information can be found in the
[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).
License
=======
This library is released under the [MIT license](LICENSE).

View File

@ -0,0 +1,36 @@
<?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.
*/
use Symfony\Polyfill\Php72 as p;
if (PHP_VERSION_ID < 70200) {
if ('\\' === DIRECTORY_SEPARATOR && !function_exists('sapi_windows_vt100_support')) {
function sapi_windows_vt100_support($stream, $enable = null) { return p\Php72::sapi_windows_vt100_support($stream, $enable); }
}
if (!function_exists('stream_isatty')) {
function stream_isatty($stream) { return p\Php72::stream_isatty($stream); }
}
if (!function_exists('utf8_encode')) {
function utf8_encode($s) { return p\Php72::utf8_encode($s); }
function utf8_decode($s) { return p\Php72::utf8_decode($s); }
}
if (!function_exists('spl_object_id')) {
function spl_object_id($s) { return p\Php72::spl_object_id($s); }
}
if (!defined('PHP_OS_FAMILY')) {
define('PHP_OS_FAMILY', p\Php72::php_os_family());
}
if (!function_exists('mb_chr')) {
function mb_ord($s, $enc = null) { return p\Php72::mb_ord($s, $enc); }
function mb_chr($code, $enc = null) { return p\Php72::mb_chr($code, $enc); }
function mb_scrub($s, $enc = null) { $enc = null === $enc ? mb_internal_encoding() : $enc; return mb_convert_encoding($s, $enc, $enc); }
}
}

View File

@ -0,0 +1,31 @@
{
"name": "symfony/polyfill-php72",
"type": "library",
"description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions",
"keywords": ["polyfill", "shim", "compatibility", "portable"],
"homepage": "https://symfony.com",
"license": "MIT",
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"require": {
"php": ">=5.3.3"
},
"autoload": {
"psr-4": { "Symfony\\Polyfill\\Php72\\": "" },
"files": [ "bootstrap.php" ]
},
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "1.11-dev"
}
}
}

View File

@ -0,0 +1,61 @@
build: false
clone_depth: 2
clone_folder: c:\projects\symfony
cache:
- composer.phar
- .phpunit -> phpunit
init:
- SET PATH=c:\php;%PATH%
- SET COMPOSER_NO_INTERACTION=1
- SET SYMFONY_DEPRECATIONS_HELPER=strict
- SET "SYMFONY_REQUIRE=>=4.2"
- SET ANSICON=121x90 (121x90)
- REG ADD "HKEY_CURRENT_USER\Software\Microsoft\Command Processor" /v DelayedExpansion /t REG_DWORD /d 1 /f
install:
- mkdir c:\php && cd c:\php
- appveyor DownloadFile https://github.com/symfony/binary-utils/releases/download/v0.1/php-7.1.3-Win32-VC14-x86.zip
- 7z x php-7.1.3-Win32-VC14-x86.zip -y >nul
- cd ext
- appveyor DownloadFile https://github.com/symfony/binary-utils/releases/download/v0.1/php_apcu-5.1.8-7.1-ts-vc14-x86.zip
- 7z x php_apcu-5.1.8-7.1-ts-vc14-x86.zip -y >nul
- cd ..
- copy /Y php.ini-development php.ini-min
- echo memory_limit=-1 >> php.ini-min
- echo serialize_precision=14 >> php.ini-min
- echo max_execution_time=1200 >> php.ini-min
- echo date.timezone="America/Los_Angeles" >> php.ini-min
- echo extension_dir=ext >> php.ini-min
- copy /Y php.ini-min php.ini-max
- echo zend_extension=php_opcache.dll >> php.ini-max
- echo opcache.enable_cli=1 >> php.ini-max
- echo extension=php_openssl.dll >> php.ini-max
- echo extension=php_apcu.dll >> php.ini-max
- echo apc.enable_cli=1 >> php.ini-max
- echo extension=php_intl.dll >> php.ini-max
- echo extension=php_mbstring.dll >> php.ini-max
- echo extension=php_fileinfo.dll >> php.ini-max
- echo extension=php_pdo_sqlite.dll >> php.ini-max
- echo extension=php_curl.dll >> php.ini-max
- copy /Y php.ini-max php.ini
- cd c:\projects\symfony
- IF NOT EXIST composer.phar (appveyor DownloadFile https://github.com/composer/composer/releases/download/1.7.1/composer.phar)
- php composer.phar self-update
- copy /Y .composer\* %APPDATA%\Composer\
- php composer.phar global require --no-progress --no-scripts --no-plugins symfony/flex dev-master
- php .github/build-packages.php "HEAD^" src\Symfony\Bridge\PhpUnit src\Symfony\Contracts
- IF %APPVEYOR_REPO_BRANCH%==master (SET COMPOSER_ROOT_VERSION=dev-master) ELSE (SET COMPOSER_ROOT_VERSION=%APPVEYOR_REPO_BRANCH%.x-dev)
- php composer.phar update --no-progress --no-suggest --ansi
- php phpunit install
test_script:
- SET X=0
- SET SYMFONY_PHPUNIT_SKIPPED_TESTS=phpunit.skipped
- copy /Y c:\php\php.ini-min c:\php\php.ini
- IF %APPVEYOR_REPO_BRANCH% neq master (rm -Rf src\Symfony\Bridge\PhpUnit)
- php phpunit src\Symfony --exclude-group benchmark,intl-data || SET X=!errorlevel!
- copy /Y c:\php\php.ini-max c:\php\php.ini
- php phpunit src\Symfony --exclude-group benchmark,intl-data || SET X=!errorlevel!
- exit %X%

View File

@ -0,0 +1,7 @@
{
"config": {
"preferred-install": {
"*": "dist"
}
}
}

View File

@ -0,0 +1,19 @@
; top-most EditorConfig file
root = true
; Unix-style newlines
[*]
charset = utf-8
end_of_line = LF
insert_final_newline = true
trim_trailing_whitespace = true
[*.{php,html,twig}]
indent_style = space
indent_size = 4
[*.md]
max_line_length = 80
[COMMIT_EDITMSG]
max_line_length = 0

View File

@ -0,0 +1,46 @@
# Console
/src/Symfony/Component/Console/Logger/ConsoleLogger.php @dunglas
# DependencyInjection
/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @dunglas
# Form
/src/Symfony/Bridge/Twig/Extension/FormExtension.php @xabbuh
/src/Symfony/Bridge/Twig/Form/* @xabbuh
/src/Symfony/Bridge/Twig/Node/FormThemeNode.php @xabbuh
/src/Symfony/Bridge/Twig/Node/RenderBlockNode.php @xabbuh
/src/Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.php @xabbuh
/src/Symfony/Bridge/Twig/Tests/Extension/FormExtension* @xabbuh
/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php @xabbuh
/src/Symfony/Bridge/Twig/Tests/TokenParser/FormThemeTokenParserTest.php @xabbuh
/src/Symfony/Bridge/Twig/TokenParser/FormThemeTokenParser.php @xabbuh
/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/FormPass.php @xabbuh
/src/Symfony/Bundle/FrameworkBundle/Resources/views/* @xabbuh
/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/FormHelper.php @xabbuh
/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/FormPassTest.php @xabbuh
/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperTableLayoutTest.php @xabbuh
/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperDivLayoutTest.php @xabbuh
/src/Symfony/Component/Form/* @xabbuh
# HttpKernel
/src/Symfony/Component/HttpKernel/Log/Logger.php @dunglas
# LDAP
/src/Symfony/Component/Ldap/* @csarrazi
# Lock
/src/Symfony/Component/Lock/* @jderusse
# Messenger
/src/Symfony/Bridge/Doctrine/Messenger/* @sroze
/src/Symfony/Component/Messenger/* @sroze
# PropertyInfo
/src/Symfony/Component/PropertyInfo/* @dunglas
/src/Symfony/Bridge/Doctrine/PropertyInfo/* @dunglas
# Serializer
/src/Symfony/Component/Serializer/* @dunglas
# WebLink
/src/Symfony/Component/WebLink/* @dunglas
# Workflow
/src/Symfony/Bridge/Twig/Extension/WorkflowExtension.php @lyrixx
/src/Symfony/Bridge/Twig/Tests/Extension/WorkflowExtensionTest.php @lyrixx
/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php @lyrixx
/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ValidateWorkflowsPass.php @lyrixx
/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/WorkflowGuardListenerPass.php @lyrixx
/src/Symfony/Component/Workflow/* @lyrixx
# Yaml
/src/Symfony/Component/Yaml/* @xabbuh

View File

@ -0,0 +1,8 @@
# Code of Conduct
This project follows a [Code of Conduct][code_of_conduct] in order to ensure an open and welcoming environment.
Please read the full text for understanding the accepted and unaccepted behavior.
Please read also the [reporting guidelines][guidelines], in case you encountered or witnessed any misbehavior.
[code_of_conduct]: https://symfony.com/doc/current/contributing/code_of_conduct/index.html
[guidelines]: https://symfony.com/doc/current/contributing/code_of_conduct/reporting_guidelines.html

View File

@ -0,0 +1,21 @@
---
name: 🐛 Bug Report
about: Report errors and problems
---
**Symfony version(s) affected**: x.y.z
**Description**
<!-- A clear and concise description of the problem. -->
**How to reproduce**
<!-- Code and/or config needed to reproduce the problem. If it's a complex bug,
create a "bug reproducer" as explained in:
https://symfony.com/doc/current/contributing/code/reproducer.html -->
**Possible Solution**
<!--- Optional: only if you have suggestions on a fix/reason for the bug -->
**Additional context**
<!-- Optional: any other context about the problem: log messages, screenshots, etc. -->

View File

@ -0,0 +1,12 @@
---
name: 🚀 Feature Request
about: RFC and ideas for new features and improvements
---
**Description**
<!-- A clear and concise description of the new feature. -->
**Example**
<!-- A simple example of the new feature in action (include PHP code, YAML config, etc.)
If the new feature changes an existing feature, include a simple before/after comparison. -->

View File

@ -0,0 +1,11 @@
---
name: ⛔ Support Question
about: See https://symfony.com/support for questions about using Symfony and its components
---
We use GitHub issues only to discuss about Symfony bugs and new features. For
this kind of questions about using Symfony or third-party bundles, please use
any of the support alternatives shown in https://symfony.com/support
Thanks!

View File

@ -0,0 +1,10 @@
---
name: ⛔ Documentation Issue
about: See https://github.com/symfony/symfony-docs/issues for documentation issues
---
Symfony Documentation has its own dedicated repository. Please open your
documentation-related issue at https://github.com/symfony/symfony-docs/issues
Thanks!

View File

@ -0,0 +1,13 @@
---
name: ⛔ Security Issue
about: See https://symfony.com/security to report security-related issues
---
⚠ PLEASE DON'T DISCLOSE SECURITY-RELATED ISSUES PUBLICLY, SEE BELOW.
If you have found a security issue in Symfony, please send the details to
security [at] symfony.com and don't disclose it publicly until we can provide a
fix for it.
More information: https://symfony.com/security

View File

@ -0,0 +1,20 @@
| Q | A
| ------------- | ---
| Branch? | master for features / 3.4 up to 4.2 for bug fixes <!-- see below -->
| Bug fix? | yes/no
| New feature? | yes/no <!-- don't forget to update src/**/CHANGELOG.md files -->
| BC breaks? | no <!-- see https://symfony.com/bc -->
| Deprecations? | yes/no <!-- don't forget to update UPGRADE-*.md and src/**/CHANGELOG.md files -->
| Tests pass? | yes <!-- please add some, will be required by reviewers -->
| Fixed tickets | #... <!-- #-prefixed issue number(s), if any -->
| License | MIT
| Doc PR | symfony/symfony-docs#... <!-- required for new features -->
<!--
Write a short README entry for your feature/bugfix here (replace this comment block.)
This will help people understand your PR and can be used as a start of the Doc PR.
Additionally:
- Bug fixes must be submitted against the lowest branch where they apply
(lowest branches are regularly merged to upper ones so they get the fixes too).
- Features and deprecations must be submitted against the master branch.
-->

View File

@ -0,0 +1,84 @@
<?php
if (3 > $_SERVER['argc']) {
echo "Usage: branch dir1 dir2 ... dirN\n";
exit(1);
}
chdir(dirname(__DIR__));
$json = ltrim(file_get_contents('composer.json'));
if ($json !== $package = preg_replace('/\n "repositories": \[\n.*?\n \],/s', '', $json)) {
file_put_contents('composer.json', $package);
}
$dirs = $_SERVER['argv'];
array_shift($dirs);
$mergeBase = trim(shell_exec(sprintf('git merge-base "%s" HEAD', array_shift($dirs))));
$packages = array();
$flags = JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE;
foreach ($dirs as $k => $dir) {
if (!system("git diff --name-only $mergeBase -- $dir", $exitStatus)) {
if ($exitStatus) {
exit($exitStatus);
}
unset($dirs[$k]);
continue;
}
echo "$dir\n";
$json = ltrim(file_get_contents($dir.'/composer.json'));
if (null === $package = json_decode($json)) {
passthru("composer validate $dir/composer.json");
exit(1);
}
$package->repositories = array(array(
'type' => 'composer',
'url' => 'file://'.str_replace(DIRECTORY_SEPARATOR, '/', dirname(__DIR__)).'/',
));
if (false === strpos($json, "\n \"repositories\": [\n")) {
$json = rtrim(json_encode(array('repositories' => $package->repositories), $flags), "\n}").','.substr($json, 1);
file_put_contents($dir.'/composer.json', $json);
}
passthru("cd $dir && tar -cf package.tar --exclude='package.tar' *");
if (!isset($package->extra->{'branch-alias'}->{'dev-master'})) {
echo "Missing \"dev-master\" branch-alias in composer.json extra.\n";
exit(1);
}
$package->version = str_replace('-dev', '.x-dev', $package->extra->{'branch-alias'}->{'dev-master'});
$package->dist['type'] = 'tar';
$package->dist['url'] = 'file://'.str_replace(DIRECTORY_SEPARATOR, '/', dirname(__DIR__))."/$dir/package.tar";
$packages[$package->name][$package->version] = $package;
$versions = @file_get_contents('https://repo.packagist.org/p/'.$package->name.'.json') ?: sprintf('{"packages":{"%s":{"dev-master":%s}}}', $package->name, file_get_contents($dir.'/composer.json'));
$versions = json_decode($versions)->packages->{$package->name};
if ($package->version === str_replace('-dev', '.x-dev', $versions->{'dev-master'}->extra->{'branch-alias'}->{'dev-master'})) {
unset($versions->{'dev-master'});
}
foreach ($versions as $v => $package) {
$packages[$package->name] += array($v => $package);
}
}
file_put_contents('packages.json', json_encode(compact('packages'), $flags));
if ($dirs) {
$json = ltrim(file_get_contents('composer.json'));
if (null === $package = json_decode($json)) {
passthru("composer validate $dir/composer.json");
exit(1);
}
$package->repositories = array(array(
'type' => 'composer',
'url' => 'file://'.str_replace(DIRECTORY_SEPARATOR, '/', dirname(__DIR__)).'/',
));
$json = rtrim(json_encode(array('repositories' => $package->repositories), $flags), "\n}").','.substr($json, 1);
file_put_contents('composer.json', $json);
}

View File

@ -0,0 +1,158 @@
<?php
error_reporting(-1);
set_error_handler(function ($type, $message, $file, $line) {
if (error_reporting()) {
throw new \ErrorException($message, 0, $type, $file, $line);
}
});
array_shift($_SERVER['argv']);
$dirs = $_SERVER['argv'];
function getRelevantContent(array $composerJson)
{
$relevantKeys = array(
'name',
'require',
'require-dev',
'conflict',
'replace',
'provide',
'minimum-stability',
'prefer-stable',
'repositories',
'extra',
);
$relevantContent = array();
foreach (array_intersect($relevantKeys, array_keys($composerJson)) as $key) {
$relevantContent[$key] = $composerJson[$key];
}
if (isset($composerJson['config']['platform'])) {
$relevantContent['config']['platform'] = $composerJson['config']['platform'];
}
return $relevantContent;
}
function getContentHash(array $composerJson)
{
$relevantContent = getRelevantContent($composerJson);
ksort($relevantContent);
return md5(json_encode($relevantContent));
}
$composerJsons = array();
foreach ($dirs as $dir) {
if (!file_exists($dir.'/composer.lock') || !$composerLock = @json_decode(file_get_contents($dir.'/composer.lock'), true)) {
@unlink($dir.'/composer.lock');
continue;
}
if (!file_exists($dir.'/composer.json') || !$composerJson = @json_decode(file_get_contents($dir.'/composer.json'), true)) {
echo "$dir/composer.json not found or invalid.\n";
@unlink($dir.'/composer.lock');
continue;
}
if (!isset($composerLock['content-hash']) || getContentHash($composerJson) !== $composerLock['content-hash']) {
echo "$dir/composer.lock is outdated.\n";
@unlink($dir.'/composer.lock');
continue;
}
$composerLock += array('packages' => array(), 'packages-dev' => array());
$composerJsons[$composerJson['name']] = array($dir, $composerLock['packages'] + $composerLock['packages-dev'], getRelevantContent($composerJson));
}
$referencedCommits = array();
foreach ($composerJsons as list($dir, $lockedPackages)) {
foreach ($lockedPackages as $lockedJson) {
if (0 !== strpos($version = $lockedJson['version'], 'dev-') && '-dev' !== substr($version, -4)) {
continue;
}
if (!isset($composerJsons[$name = $lockedJson['name']])) {
echo "$dir/composer.lock references missing $name.\n";
@unlink($dir.'/composer.lock');
continue 2;
}
if (isset($composerJsons[$name][2]['repositories']) && !isset($lockedJson['repositories'])) {
// the locked package has been patched locally but the lock references a commit,
// which means the referencing package itself is not modified
continue;
}
foreach (array('minimum-stability', 'prefer-stable') as $key) {
if (array_key_exists($key, $composerJsons[$name][2])) {
$lockedJson[$key] = $composerJsons[$name][2][$key];
}
}
// use weak comparison to ignore ordering
if (getRelevantContent($lockedJson) != $composerJsons[$name][2]) {
echo "$dir/composer.lock is not in sync with $name.\n";
@unlink($dir.'/composer.lock');
continue 2;
}
if ($lockedJson['dist']['reference']) {
$referencedCommits[$name][$lockedJson['dist']['reference']][] = $dir;
}
}
}
if (!$referencedCommits) {
return;
}
@mkdir($_SERVER['HOME'].'/.cache/composer/repo/https---repo.packagist.org', 0777, true);
$ch = null;
$mh = curl_multi_init();
$sh = curl_share_init();
curl_share_setopt($sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);
curl_share_setopt($sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
curl_share_setopt($sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);
$chs = array();
foreach ($referencedCommits as $name => $dirsByCommit) {
$chs[] = $ch = array(curl_init(), fopen($_SERVER['HOME'].'/.cache/composer/repo/https---repo.packagist.org/provider-'.strtr($name, '/', '$').'.json', 'wb'));
curl_setopt($ch[0], CURLOPT_URL, 'https://repo.packagist.org/p/'.$name.'.json');
curl_setopt($ch[0], CURLOPT_FILE, $ch[1]);
curl_setopt($ch[0], CURLOPT_SHARE, $sh);
curl_multi_add_handle($mh, $ch[0]);
}
do {
curl_multi_exec($mh, $active);
curl_multi_select($mh);
} while ($active);
foreach ($chs as list($ch, $fd)) {
curl_multi_remove_handle($mh, $ch);
curl_close($ch);
fclose($fd);
}
foreach ($referencedCommits as $name => $dirsByCommit) {
$repo = file_get_contents($_SERVER['HOME'].'/.cache/composer/repo/https---repo.packagist.org/provider-'.strtr($name, '/', '$').'.json');
$repo = json_decode($repo, true);
foreach ($repo['packages'][$name] as $version) {
unset($referencedCommits[$name][$version['source']['reference']]);
}
}
foreach ($referencedCommits as $name => $dirsByCommit) {
foreach ($dirsByCommit as $dirs) {
foreach ($dirs as $dir) {
if (file_exists($dir.'/composer.lock')) {
echo "$dir/composer.lock references old commit for $name.\n";
@unlink($dir.'/composer.lock');
}
}
}
}

View File

@ -0,0 +1,8 @@
vendor/
composer.lock
phpunit.xml
.php_cs.cache
composer.phar
package.tar
/packages.json
/.phpunit

View File

@ -0,0 +1,57 @@
<?php
if (!file_exists(__DIR__.'/src')) {
exit(0);
}
return PhpCsFixer\Config::create()
->setRules([
'@Symfony' => true,
'@Symfony:risky' => true,
'@PHPUnit48Migration:risky' => true,
'php_unit_no_expectation_annotation' => false, // part of `PHPUnitXYMigration:risky` ruleset, to be enabled when PHPUnit 4.x support will be dropped, as we don't want to rewrite exceptions handling twice
'array_syntax' => ['syntax' => 'short'],
'fopen_flags' => false,
'ordered_imports' => true,
'protected_to_private' => false,
// Part of @Symfony:risky in PHP-CS-Fixer 2.13.0. To be removed from the config file once upgrading
'native_function_invocation' => ['include' => ['@compiler_optimized'], 'scope' => 'namespaced'],
// Part of future @Symfony ruleset in PHP-CS-Fixer To be removed from the config file once upgrading
'phpdoc_types_order' => ['null_adjustment' => 'always_last', 'sort_algorithm' => 'none'],
])
->setRiskyAllowed(true)
->setFinder(
PhpCsFixer\Finder::create()
->in(__DIR__.'/src')
->append([__FILE__])
->exclude([
'Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/Fixtures',
// directories containing files with content that is autogenerated by `var_export`, which breaks CS in output code
'Symfony/Component/DependencyInjection/Tests/Fixtures',
'Symfony/Component/Routing/Tests/Fixtures/dumper',
// fixture templates
'Symfony/Component/Templating/Tests/Fixtures/templates',
'Symfony/Bundle/FrameworkBundle/Tests/Fixtures/TemplatePathsCache',
'Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Resources/Custom',
// generated fixtures
'Symfony/Component/VarDumper/Tests/Fixtures',
'Symfony/Component/VarExporter/Tests/Fixtures',
// resource templates
'Symfony/Bundle/FrameworkBundle/Resources/views/Form',
// explicit trigger_error tests
'Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/',
])
// Support for older PHPunit version
->notPath('Symfony/Bridge/PhpUnit/SymfonyTestsListener.php')
// file content autogenerated by `var_export`
->notPath('Symfony/Component/Translation/Tests/fixtures/resources.php')
// test template
->notPath('Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Resources/Custom/_name_entry_label.html.php')
// explicit heredoc test
->notPath('Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Resources/views/translation.html.php')
// explicit trigger_error tests
->notPath('Symfony/Component/Debug/Tests/DebugClassLoaderTest.php')
// invalid annotations on purpose
->notPath('Symfony/Component/DependencyInjection/Tests/Fixtures/includes/autowiring_classes.php')
)
;

View File

@ -0,0 +1,255 @@
language: php
dist: trusty
git:
depth: 2
addons:
apt_packages:
- parallel
- language-pack-fr-base
- ldap-utils
- slapd
- zookeeperd
- libzookeeper-mt-dev
env:
global:
- MIN_PHP=7.1.3
- SYMFONY_PROCESS_PHP_TEST_BINARY=~/.phpenv/shims/php
- MESSENGER_AMQP_DSN=amqp://localhost/%2f/messages
matrix:
include:
- php: 7.1
- php: 7.2
env: deps=high
- php: 7.3
env: deps=low
fast_finish: true
cache:
directories:
- .phpunit
- php-$MIN_PHP
- ~/php-ext
services:
- memcached
- mongodb
- redis-server
- rabbitmq
- docker
before_install:
- |
# Enable Sury ppa
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 6B05F25D762E3157
sudo add-apt-repository -y ppa:ondrej/php
sudo rm /etc/apt/sources.list.d/google-chrome.list
sudo rm /etc/apt/sources.list.d/mongodb-3.4.list
sudo apt update
sudo apt install -y librabbitmq-dev libsodium-dev
- |
# Start Redis cluster
docker pull grokzen/redis-cluster:4.0.8
docker run -d -p 7000:7000 -p 7001:7001 -p 7002:7002 -p 7003:7003 -p 7004:7004 -p 7005:7005 --name redis-cluster grokzen/redis-cluster:4.0.8
export REDIS_CLUSTER_HOSTS='localhost:7000 localhost:7001 localhost:7002 localhost:7003 localhost:7004 localhost:7005'
- |
# General configuration
set -e
stty cols 120
mkdir /tmp/slapd
slapd -f src/Symfony/Component/Ldap/Tests/Fixtures/conf/slapd.conf -h ldap://localhost:3389 &
[ -d ~/.composer ] || mkdir ~/.composer
cp .composer/* ~/.composer/
export PHPUNIT=$(readlink -f ./phpunit)
export PHPUNIT_X="$PHPUNIT --exclude-group tty,benchmark,intl-data"
export COMPOSER_UP='composer update --no-progress --no-suggest --ansi'
export COMPONENTS=$(find src/Symfony -mindepth 2 -type f -name phpunit.xml.dist -printf '%h\n')
find ~/.phpenv -name xdebug.ini -delete
nanoseconds () {
local cmd="date"
local format="+%s%N"
local os=$(uname)
if hash gdate > /dev/null 2>&1; then
cmd="gdate"
elif [[ "$os" = Darwin ]]; then
format="+%s000000000"
fi
$cmd -u $format
}
export -f nanoseconds
# tfold is a helper to create folded reports
tfold () {
local title="🐘 $PHP $1"
local fold=$(echo $title | sed -r 's/[^-_A-Za-z0-9]+/./g')
shift
local id=$(printf %08x $(( RANDOM * RANDOM )))
local start=$(nanoseconds)
echo -e "travis_fold:start:$fold"
echo -e "travis_time:start:$id"
echo -e "\\e[1;34m$title\\e[0m"
bash -xc "$*" 2>&1
local ok=$?
local end=$(nanoseconds)
echo -e "\\ntravis_time:end:$id:start=$start,finish=$end,duration=$(($end-$start))"
(exit $ok) &&
echo -e "\\e[32mOK\\e[0m $title\\n\\ntravis_fold:end:$fold" ||
echo -e "\\e[41mKO\\e[0m $title\\n"
(exit $ok)
}
export -f tfold
# tpecl is a helper to compile and cache php extensions
tpecl () {
local ext_name=$1
local ext_so=$2
local INI=$3
local ext_dir=$(php -r "echo ini_get('extension_dir');")
local ext_cache=~/php-ext/$(basename $ext_dir)/$ext_name
if [[ -e $ext_cache/$ext_so ]]; then
echo extension = $ext_cache/$ext_so >> $INI
else
rm ~/.pearrc /tmp/pear 2>/dev/null || true
mkdir -p $ext_cache
echo yes | pecl install -f $ext_name &&
cp $ext_dir/$ext_so $ext_cache
fi
}
export -f tpecl
- |
# Install sigchild-enabled PHP to test the Process component on the lowest PHP matrix line
if [[ ! $deps && $TRAVIS_PHP_VERSION = ${MIN_PHP%.*} && ! -d php-$MIN_PHP/sapi ]]; then
wget http://php.net/get/php-$MIN_PHP.tar.bz2/from/this/mirror -O - | tar -xj &&
(cd php-$MIN_PHP && ./configure --enable-sigchild --enable-pcntl && make -j2)
fi
- |
# php.ini configuration
for PHP in $TRAVIS_PHP_VERSION $php_extra; do
phpenv global $PHP 2>/dev/null || (cd / && wget https://s3.amazonaws.com/travis-php-archives/binaries/ubuntu/14.04/x86_64/php-$PHP.tar.bz2 -O - | tar -xj)
INI=~/.phpenv/versions/$PHP/etc/conf.d/travis.ini
echo date.timezone = Europe/Paris >> $INI
echo memory_limit = -1 >> $INI
echo session.gc_probability = 0 >> $INI
echo opcache.enable_cli = 1 >> $INI
echo apc.enable_cli = 1 >> $INI
echo extension = redis.so >> $INI
echo extension = memcached.so >> $INI
done
- |
# Install extra PHP extensions
for PHP in $TRAVIS_PHP_VERSION $php_extra; do
export PHP=$PHP
phpenv global $PHP
INI=~/.phpenv/versions/$PHP/etc/conf.d/travis.ini
if ! php --ri sodium > /dev/null; then
tfold ext.libsodium tpecl libsodium sodium.so $INI
fi
tfold ext.apcu tpecl apcu-5.1.16 apcu.so $INI
tfold ext.mongodb tpecl mongodb-1.6.0alpha1 mongodb.so $INI
tfold ext.igbinary tpecl igbinary-2.0.8 igbinary.so $INI
tfold ext.zookeeper tpecl zookeeper-0.7.1 zookeeper.so $INI
tfold ext.amqp tpecl amqp-1.9.4 amqp.so $INI
done
- |
# Load fixtures
if [[ ! $skip ]]; then
ldapadd -h localhost:3389 -D cn=admin,dc=symfony,dc=com -w symfony -f src/Symfony/Component/Ldap/Tests/Fixtures/data/base.ldif &&
ldapadd -h localhost:3389 -D cn=admin,dc=symfony,dc=com -w symfony -f src/Symfony/Component/Ldap/Tests/Fixtures/data/fixtures.ldif
fi
install:
- |
# Create local composer packages for each patched components and reference them in composer.json files when cross-testing components
if [[ ! $deps ]]; then
php .github/build-packages.php HEAD^ src/Symfony/Bridge/PhpUnit src/Symfony/Contracts
else
export SYMFONY_DEPRECATIONS_HELPER=weak &&
cp composer.json composer.json.orig &&
echo -e '{\n"require":{'"$(grep phpunit-bridge composer.json)"'"php":"*"},"minimum-stability":"dev"}' > composer.json &&
php .github/build-packages.php HEAD^ $COMPONENTS &&
mv composer.json composer.json.phpunit &&
mv composer.json.orig composer.json
fi
- |
# For the master branch, when deps=high, the version before master is checked out and tested with the locally patched components
if [[ $deps = high && $TRAVIS_BRANCH = master ]]; then
SYMFONY_VERSION=$(git ls-remote --heads | grep -o '/[1-9].*' | tail -n 1 | sed s/.//) &&
git fetch origin $SYMFONY_VERSION &&
git checkout -m FETCH_HEAD &&
COMPONENTS=$(find src/Symfony -mindepth 2 -type f -name phpunit.xml.dist -printf '%h\n')
else
SYMFONY_VERSION=$(cat composer.json | grep '^ *"dev-master". *"[1-9]' | grep -o '[0-9.]*')
fi
- |
# Skip the phpunit-bridge on not-master branches when $deps is empty
if [[ ! $deps && $TRAVIS_BRANCH != master ]]; then
COMPONENTS=$(find src/Symfony -mindepth 3 -type f -name phpunit.xml.dist -not -wholename '*/Bridge/PhpUnit/*' -printf '%h\n')
fi
- |
# Install symfony/flex
if [[ $deps = low ]]; then
export SYMFONY_REQUIRE='>=2.3'
else
export SYMFONY_REQUIRE=">=$SYMFONY_VERSION"
fi
composer global require --no-progress --no-scripts --no-plugins symfony/flex dev-master
- |
# Legacy tests are skipped when deps=high and when the current branch version has not the same major version number than the next one
[[ $deps = high && ${SYMFONY_VERSION%.*} != $(git show $(git ls-remote --heads | grep -FA1 /$SYMFONY_VERSION | tail -n 1):composer.json | grep '^ *"dev-master". *"[1-9]' | grep -o '[0-9]*' | head -n 1) ]] && LEGACY=,legacy
export COMPOSER_ROOT_VERSION=$SYMFONY_VERSION.x-dev
if [[ $deps ]]; then mv composer.json.phpunit composer.json; fi
- php -i
- |
run_tests () {
set -e
export PHP=$1
if [[ $PHP != $TRAVIS_PHP_VERSION && $TRAVIS_PULL_REQUEST != false ]]; then
echo -e "\\n\\e[1;34mIntermediate PHP version $PHP is skipped for pull requests.\\e[0m"
break
fi
phpenv global $PHP
([[ $deps ]] && cd src/Symfony/Component/HttpFoundation; composer config platform.ext-mongodb 1.6.0; composer require --dev --no-update mongodb/mongodb)
tfold 'composer update' $COMPOSER_UP
tfold 'phpunit install' ./phpunit install
if [[ $deps = high ]]; then
echo "$COMPONENTS" | parallel --gnu -j10% "tfold {} 'cd {} && $COMPOSER_UP && $PHPUNIT_X$LEGACY'"
elif [[ $deps = low ]]; then
[[ -e ~/php-ext/composer-lowest.lock.tar ]] && tar -xf ~/php-ext/composer-lowest.lock.tar
tar -cf ~/php-ext/composer-lowest.lock.tar --files-from /dev/null
php .github/rm-invalid-lowest-lock-files.php $COMPONENTS
echo "$COMPONENTS" | parallel --gnu -j10% "tfold {} 'cd {} && ([ -e composer.lock ] && ${COMPOSER_UP/update/install} || $COMPOSER_UP --prefer-lowest --prefer-stable) && $PHPUNIT_X'"
echo "$COMPONENTS" | xargs -n1 -I{} tar --append -f ~/php-ext/composer-lowest.lock.tar {}/composer.lock
else
echo "$COMPONENTS" | parallel --gnu "tfold {} $PHPUNIT_X {}"
tfold src/Symfony/Component/Console.tty $PHPUNIT src/Symfony/Component/Console --group tty
if [[ $PHP = ${MIN_PHP%.*} ]]; then
export PHP=$MIN_PHP
tfold src/Symfony/Component/Process.sigchild SYMFONY_DEPRECATIONS_HELPER=weak php-$MIN_PHP/sapi/cli/php ./phpunit --colors=always src/Symfony/Component/Process/
fi
fi
}
script:
- for PHP in $TRAVIS_PHP_VERSION $php_extra; do (run_tests $PHP); done

View File

@ -0,0 +1,919 @@
CHANGELOG for 4.0.x
===================
This changelog references the relevant changes (bug and security fixes) done
in 4.0 minor versions.
To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash
To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v4.0.0...v4.0.1
* 4.0.14 (2018-08-01)
* security #cve-2018-14774 [HttpKernel] fix trusted headers management in HttpCache and InlineFragmentRenderer (nicolas-grekas)
* security #cve-2018-14773 [HttpFoundation] Remove support for legacy and risky HTTP headers (nicolas-grekas)
* bug #28003 [HttpKernel] Fixes invalid REMOTE_ADDR in inline subrequest when configuring trusted proxy with subnet (netiul)
* bug #28007 [FrameworkBundle] fixed guard event names for transitions (destillat)
* bug #28045 [HttpFoundation] Fix Cookie::isCleared (ro0NL)
* bug #28080 [HttpFoundation] fixed using _method parameter with invalid type (Phobetor)
* bug #28052 [HttpKernel] Fix merging bindings for controllers' locators (nicolas-grekas)
* 4.0.13 (2018-07-23)
* bug #28005 [HttpKernel] Fixed templateExists on parse error of the template name (yceruto)
* bug #27997 Serbo-Croatian has Serbian plural rule (kylekatarnls)
* bug #26193 Fix false-positive deprecation notices for TranslationLoader and WriteCheckSessionHandler (iquito)
* bug #27941 [WebProfilerBundle] Fixed icon alignment issue using Bootstrap 4.1.2 (jmsche)
* bug #27937 [HttpFoundation] reset callback on StreamedResponse when setNotModified() is called (rubencm)
* bug #27927 [HttpFoundation] Suppress side effects in 'get' and 'has' methods of NamespacedAttributeBag (webnet-fr)
* bug #27923 [Form/Profiler] Massively reducing memory footprint of form profiling pages... (VincentChalnot)
* bug #27918 [Console] correctly return parameter's default value on "--" (seschwar)
* bug #27904 [Filesystem] fix lock file permissions (fritzmg)
* bug #27903 [Lock] fix lock file permissions (fritzmg)
* bug #27889 [Form] Replace .initialism with .text-uppercase. (vudaltsov)
* bug #27902 Fix the detection of the Process new argument (stof)
* bug #27885 [HttpFoundation] don't encode cookie name for BC (nicolas-grekas)
* bug #27782 [DI] Fix dumping ignore-on-uninitialized references to synthetic services (nicolas-grekas)
* bug #27435 [OptionResolver] resolve arrays (Doctrs)
* bug #27728 [TwigBridge] Fix missing path and separators in loader paths list on debug:twig output (yceruto)
* bug #27837 [PropertyInfo] Fix dock block lookup fallback loop (DerManoMann)
* bug #27758 [WebProfilerBundle] Prevent toolbar links color override by css (alcalyn)
* bug #27847 [Security] Fix accepting null as $uidKey in LdapUserProvider (louhde)
* bug #27834 [DI] Don't show internal service id on binding errors (nicolas-grekas)
* bug #27831 Check for Hyper terminal on all operating systems. (azjezz)
* bug #27794 Add color support for Hyper terminal . (azjezz)
* bug #27809 [HttpFoundation] Fix tests: new message for status 425 (dunglas)
* bug #27618 [PropertyInfo] added handling of nullable types in PhpDoc (oxan)
* bug #27659 [HttpKernel] Make AbstractTestSessionListener compatible with CookieClearingLogoutHandler (thewilkybarkid)
* bug #27752 [Cache] provider does not respect option maxIdLength with versioning enabled (Constantine Shtompel)
* bug #27776 [ProxyManagerBridge] Fix support of private services (bis) (nicolas-grekas)
* bug #27714 [HttpFoundation] fix session tracking counter (nicolas-grekas, dmaicher)
* bug #27747 [HttpFoundation] fix registration of session proxies (nicolas-grekas)
* bug #27722 Redesign the Debug error page in prod (javiereguiluz)
* bug #27716 [DI] fix dumping deprecated service in yaml (nicolas-grekas)
* 4.0.12 (2018-06-25)
* bug #27626 [TwigBundle][DX] Only add the Twig WebLinkExtension if the WebLink component is enabled (thewilkybarkid)
* bug #27701 [SecurityBundle] Dont throw if "security.http_utils" is not found (nicolas-grekas)
* bug #27690 [DI] Resolve env placeholder in logs (ro0NL)
* bug #26534 allow_extra_attributes does not throw an exception as documented (deviantintegral)
* bug #27668 [Lock] use 'r+' for fopen (fixes issue on Solaris) (fritzmg)
* bug #27669 [Filesystem] fix file lock on SunOS (fritzmg)
* bug #27662 [HttpKernel] fix handling of nested Error instances (xabbuh)
* bug #26845 [Config] Fixing GlobResource when inside phar archive (vworldat)
* bug #27382 [Form] Fix error when rendering a DateIntervalType form with exactly 0 weeks (krixon)
* bug #27309 Fix surrogate not using original request (Toflar)
* bug #27467 [HttpKernel] fix session tracking in surrogate master requests (nicolas-grekas)
* bug #27630 [Validator][Form] Remove BOM in some xlf files (gautierderuette)
* bug #27596 [Framework][Workflow] Added support for interfaces (vudaltsov)
* bug #27593 [ProxyManagerBridge] Fixed support of private services (nicolas-grekas)
* bug #27591 [VarDumper] Fix dumping ArrayObject and ArrayIterator instances (nicolas-grekas)
* bug #27581 Fix bad method call with guard authentication + session migration (weaverryan)
* bug #27576 [Cache] Fix expiry comparisons in array-based pools (nicolas-grekas)
* bug #27556 Avoiding session migration for stateless firewall UsernamePasswordJsonAuthenticationListener (weaverryan)
* bug #27452 Avoid migration on stateless firewalls (weaverryan)
* bug #27568 [DI] Deduplicate generated proxy classes (nicolas-grekas)
* bug #27326 [Serializer] deserialize from xml: Fix a collection that contains the only one element (webnet-fr)
* bug #27567 [PhpUnitBridge] Fix error on some Windows OS (Nsbx)
* bug #27357 [Lock] Remove released semaphore (jderusse)
* bug #27416 TagAwareAdapter over non-binary memcached connections corrupts memcache (Aleksey Prilipko)
* bug #27514 [Debug] Pass previous exception to FatalErrorException (pmontoya)
* bug #27516 Revert "bug #26138 [HttpKernel] Catch HttpExceptions when templating is not installed (cilefen)" (nicolas-grekas)
* bug #27318 [Cache] memcache connect should not add duplicate entries on sequential calls (Aleksey Prilipko)
* bug #27389 [Serializer] Fix serializer tries to denormalize null values on nullable properties (ogizanagi)
* bug #27272 [FrameworkBundle] Change priority of AddConsoleCommandPass to TYPE_BEFORE_REMOVING (upyx)
* bug #27396 [HttpKernel] fix registering IDE links (nicolas-grekas)
* bug #26973 [HttpKernel] Set first trusted proxy as REMOTE_ADDR in InlineFragmentRenderer. (kmadejski)
* bug #27303 [Process] Consider "executable" suffixes first on Windows (sanmai)
* bug #27297 Triggering RememberMe's loginFail() when token cannot be created (weaverryan)
* bug #27344 [HttpKernel] reset kernel start time on reboot (kiler129)
* bug #27365 [Serializer] Check the value of enable_max_depth if defined (dunglas)
* bug #27358 [PhpUnitBridge] silence some stderr outputs (ostrolucky)
* bug #27366 [DI] never inline lazy services (nicolas-grekas)
* 4.0.11 (2018-05-25)
* bug #27364 [DI] Fix bad exception on uninitialized references to non-shared services (nicolas-grekas)
* bug #27359 [HttpFoundation] Fix perf issue during MimeTypeGuesser intialization (nicolas-grekas)
* security #cve-2018-11408 [SecurityBundle] Fail if security.http_utils cannot be configured
* security #cve-2018-11406 clear CSRF tokens when the user is logged out
* security #cve-2018-11385 migrating session for UsernamePasswordJsonAuthenticationListener
* security #cve-2018-11385 Adding session authentication strategy to Guard to avoid session fixation
* security #cve-2018-11385 Adding session strategy to ALL listeners to avoid *any* possible fixation
* security #cve-2018-11386 [HttpFoundation] Break infinite loop in PdoSessionHandler when MySQL is in loose mode
* bug #27341 [WebProfilerBundle] Fixed validator/dump trace CSS (yceruto)
* bug #27337 [FrameworkBundle] fix typo in CacheClearCommand (emilielorenzo)
* 4.0.10 (2018-05-21)
* bug #27264 [Validator] Use strict type in URL validator (mimol91)
* bug #27267 [DependencyInjection] resolve array env vars (jamesthomasonjr)
* bug #26781 [Form] Fix precision of MoneyToLocalizedStringTransformer's divisions on transform() (syastrebov)
* bug #27286 [Translation] Add Occitan plural rule (kylekatarnls)
* bug #27271 [DI] Allow defining bindings on ChildDefinition (nicolas-grekas)
* bug #27246 Disallow invalid characters in session.name (ostrolucky)
* bug #27287 [PropertyInfo] fix resolving parent|self type hints (nicolas-grekas)
* bug #27281 [HttpKernel] Fix dealing with self/parent in ArgumentMetadataFactory (fabpot)
* bug #24805 [Security] Fix logout (MatTheCat)
* bug #27265 [DI] Shared services should not be inlined in non-shared ones (nicolas-grekas)
* bug #27141 [Process] Suppress warnings when open_basedir is non-empty (cbj4074)
* bug #27250 [Session] limiting :key for GET_LOCK to 64 chars (oleg-andreyev)
* bug #27237 [Debug] Fix populating error_get_last() for handled silent errors (nicolas-grekas)
* bug #27232 [Cache][Lock] Fix usages of error_get_last() (nicolas-grekas)
* bug #27236 [Filesystem] Fix usages of error_get_last() (nicolas-grekas)
* bug #27191 [DI] Display previous error messages when throwing unused bindings (nicolas-grekas)
* bug #27231 [FrameworkBundle] Fix cache:clear on vagrant (nicolas-grekas)
* bug #27222 [WebProfilerBundle][Cache] Fix misses calculation when calling getItems (fsevestre)
* bug #27227 [HttpKernel] Handle NoConfigurationException "onKernelException()" (nicolas-grekas)
* bug #27152 [HttpFoundation] use brace-style regex delimiters (xabbuh)
* bug #27158 [Cache] fix logic for fetching tag versions on TagAwareAdapter (dmaicher)
* bug #27143 [Console] By default hide the short exception trace line from exception messages in Symfony's commands (yceruto)
* bug #27133 [Doctrine Bridge] fix priority for doctrine event listeners (dmaicher)
* bug #27135 [FrameworkBundle] Use the correct service id for CachePoolPruneCommand in its compiler pass (DemonTPx)
* feature #24896 Add CODE_OF_CONDUCT.md (egircys)
* 4.0.9 (2018-04-30)
* bug #27074 [Debug][WebProfilerBundle] Fix setting file link format (lyrixx, nicolas-grekas)
* bug #27088 ResolveBindingsPass: Don't throw error for unused service, missing parent class (weaverryan)
* bug #27086 [PHPUnitBridge] Add an implementation just for php 7.0 (greg0ire)
* bug #26138 [HttpKernel] Catch HttpExceptions when templating is not installed (cilefen)
* bug #27007 [Cache] TagAwareAdapterInterface::invalidateTags() should commit deferred items (nicolas-grekas)
* bug #27067 [HttpFoundation] Fix setting session-related ini settings (e-moe)
* bug #27061 [HttpKernel] Don't clean legacy containers that are still loaded (nicolas-grekas)
* bug #27064 [VarDumper] Fix HtmlDumper classes match (ogizanagi)
* bug #27016 [Security][Guard] GuardAuthenticationProvider::authenticate cannot return null (biomedia-thomas)
* bug #26831 [Bridge/Doctrine] count(): Parameter must be an array or an object that implements Countable (gpenverne)
* bug #27044 [Security] Skip user checks if not implementing UserInterface (chalasr)
* bug #27025 [DI] Add check of internal type to ContainerBuilder::getReflectionClass (upyx)
* bug #26994 [PhpUnitBridge] Add type hints (greg0ire)
* bug #26014 [Security] Fixed being logged out on failed attempt in guard (iltar)
* bug #25348 [HttpFoundation] Send cookies using header() to fix "SameSite" ones (nicolas-grekas, cvilleger)
* bug #26910 Use new PHP7.2 functions in hasColorSupport (johnstevenson)
* bug #26999 [VarDumper] Fix dumping of SplObjectStorage (corphi)
* bug #25841 [DoctrineBridge] Fix bug when indexBy is meta key in PropertyInfo\DoctrineExtractor (insekticid)
* bug #26983 [TwigBridge] [Bootstrap 4] Fix PercentType error rendering. (alexismarquis)
* bug #26980 [TwigBundle] fix formatting arguments in plaintext format (xabbuh)
* bug #26886 Don't assume that file binary exists on *nix OS (teohhanhui)
* bug #26959 [Console] Fix PSR exception context key (scaytrase)
* bug #26899 [Routing] Fix loading multiple class annotations for invokable classes (1ed)
* bug #26643 Fix that ESI/SSI processing can turn a "private" response "public" (mpdude)
* bug #26932 [Form] Fixed trimming choice values (HeahDude)
* bug #26922 [TwigBundle] fix rendering exception stack traces (xabbuh)
* bug #26773 [HttpKernel] Make ServiceValueResolver work if controller namespace starts with a backslash in routing (mathieutu)
* bug #26870 Add d-block to bootstrap 4 alerts (Normunds)
* bug #26857 [HttpKernel] Dont create mock cookie for new sessions in tests (nicolas-grekas)
* bug #26875 [Console] Don't go past exact matches when autocompleting (nicolas-grekas)
* bug #26823 [Validator] Fix LazyLoadingMetadataFactory with PSR6Cache for non classname if tested values isn't existing class (Pascal Montoya, pmontoya)
* bug #26834 [Yaml] Throw parse error on unfinished inline map (nicolas-grekas)
* 4.0.8 (2018-04-06)
* bug #26802 [Security] register custom providers on ExpressionLanguage directly (dmaicher)
* bug #26794 [PhpUnitBridge] Catch deprecation error handler (cvilleger)
* bug #26788 [Security] Load the user before pre/post auth checks when needed (chalasr)
* bug #26792 [Routing] Fix throwing NoConfigurationException instead of 405 (nicolas-grekas)
* bug #26774 [SecurityBundle] Add missing argument to security.authentication.provider.simple (i3or1s, chalasr)
* bug #26763 [Finder] Remove duplicate slashes in filenames (helhum)
* bug #26758 [WebProfilerBundle][HttpKernel] Make FileLinkFormatter URL format generation lazy (nicolas-grekas)
* 4.0.7 (2018-04-03)
* bug #26387 [Yaml] Fix regression when trying to parse multiline (antograssiot)
* bug #26749 Add PHPDbg support to HTTP components (hkdobrev)
* bug #26609 [Console] Fix check of color support on Windows (mlocati)
* bug #26727 [HttpCache] Unlink tmp file on error (Chansig)
* bug #26675 [HttpKernel] DumpDataCollector: do not flush when a dumper is provided (ogizanagi)
* bug #26663 [TwigBridge] Fix rendering of currency by MoneyType (ro0NL)
* bug #26595 [DI] Do not suggest writing an implementation when multiple exist (chalasr)
* bug #26662 [DI] Fix hardcoded cache dir for warmups (nicolas-grekas)
* bug #26677 Support phpdbg SAPI in Debug::enable() (hkdobrev)
* bug #26600 [Routing] Fixed the importing of files using glob patterns that match multiple resources (skalpa)
* bug #26589 [Ldap] cast to string when checking empty passwords (ismail1432)
* bug #26626 [WebProfilerBundle] use the router to resolve file links (nicolas-grekas)
* bug #26634 [DI] Cleanup remainings from autoregistration (nicolas-grekas)
* bug #26635 [DI] Dont tell about autoregistration in strict autowiring mode (nicolas-grekas)
* bug #26621 [Form] no type errors with invalid submitted data types (xabbuh)
* bug #26612 [PHPunit] suite variable should be used (prisis)
* bug #26337 [Finder] Fixed leading/trailing / in filename (lyrixx)
* bug #26584 [TwigBridge] allow html5 compatible rendering of forms with null names (systemist)
* bug #24401 [Form] Change datetime to datetime-local for HTML5 datetime input (pierredup)
* bug #26513 [FrameworkBundle] Respect debug mode when warm up annotations (Strate)
* bug #26370 [Security] added userChecker to SimpleAuthenticationProvider (i3or1s)
* bug #26569 [BrowserKit] Fix cookie path handling when $domain is null (dunglas)
* bug #26273 [Security][Profiler] Display the original expression in 'Access decision log' (lyrixx)
* bug #26427 [DependencyInjection] fix regression when extending the Container class without a constructor (lsmith77)
* bug #26562 [Bridge\PhpUnit] Cannot autoload class "\Symfony\Bridge\PhpUnit\SymfonyTestsListener" (Jake Bishop)
* bug #26598 Fixes #26563 (open_basedir restriction in effect) (temperatur)
* bug #26568 [Debug] Reset previous exception handler earlier to prevent infinite loop (nicolas-grekas)
* bug #26590 Make sure form errors is valid HTML (Nyholm)
* bug #26567 [DoctrineBridge] Don't rely on ClassMetadataInfo->hasField in DoctrineOrmTypeGuesser anymore (fancyweb)
* feature #26408 Readd 'form_label_errors' block to disable errors on form labels (birkof)
* bug #26591 [TwigBridge] Make sure we always render errors. Eventhough labels are disabled (Nyholm)
* bug #26356 [FrameworkBundle] HttpCache is not longer abstract (lyrixx)
* bug #26548 [DomCrawler] Change bad wording in ChoiceFormField::untick (dunglas)
* bug #26482 [PhpUnitBridge] Ability to use different composer.json file (amcastror)
* bug #26443 [Fix][HttpFoundation] Fix the updating of timestamp in the MemcachedSessionHandler (Alessandro Loffredo)
* bug #26400 [Config] ReflectionClassResource check abstract class (andrey1s)
* bug #26433 [DomCrawler] extract(): fix a bug when the attribute list is empty (dunglas)
* bug #26041 Display the Welcome Page when there is no homepage defined (javiereguiluz)
* bug #26452 [Intl] Load locale aliases to support alias fallbacks (jakzal)
* bug #26450 [CssSelector] Fix CSS identifiers parsing - they can start with dash (jakubkulhan)
* 4.0.6 (2018-03-05)
* bug #26393 [DI] Skip resource tracking if disabled (chalasr)
* bug #26403 fix the handling of timestamp in the MongoDBSessionHandler (hjanuschka)
* bug #26355 [DI] Fix missing "id" normalization when dumping the container (nicolas-grekas)
* bug #26368 [WebProfilerBundle] Fix Debug toolbar breaks app (xkobal)
* bug #26369 Use fill instead of style for svg colors (rpkamp)
* bug #26358 [FrameworkBundle] Silence "Failed to remove directory" on cache:clear (nicolas-grekas)
* 4.0.5 (2018-03-01)
* bug #26327 [Form][WCAG] Errors sign for people that do not see colors (Nyholm)
* bug #26326 [Form][WCAG] Added role="presentation" on tables & removed bootstrap4 table (Nyholm)
* bug #26325 [Form][WCAG] Add hidden labels on date and time fields (Nyholm)
* bug #26338 [Debug] Keep previous errors of Error instances (Philipp91)
* bug #26328 [Form][WCAG] Fixed HTML errors (Nyholm)
* bug #26290 [FrameworkBundle] [Console][DX] add a warning when command is not found (Simperfit)
* bug #26318 [Routing] Fix GC control of PHP-DSL (nicolas-grekas)
* bug #26312 [Routing] Don't throw 405 when scheme requirement doesn't match (nicolas-grekas)
* bug #26275 Set controller without __invoke method from invokable class (Tobion)
* bug #26298 Fix ArrayInput::toString() for InputArgument::IS_ARRAY args (maximium)
* bug #26177 Update excluded_ajax_paths for sf4 (jenaye)
* bug #26289 [Security] Add missing use of Role (tony-tran)
* bug #26286 [Security] Add missing use for RoleInterface (tony-tran)
* bug #26265 [PropertyInfo] throw exception if docblock factory does not exist (xabbuh)
* bug #26247 [Translation] Process multiple segments within a single unit. (timewasted)
* bug #26254 fix custom radios/inputs for checkbox/radio type (mssimi)
* bug #26234 [FrameworkBundle] Add missing XML config for circular_reference_handler (dunglas)
* bug #26236 [PropertyInfo] ReflectionExtractor: give a chance to other extractors if no properties (dunglas)
* bug #26227 Add support for URL-like DSNs for the PdoSessionHandler (stof)
* bug #25557 [WebProfilerBundle] add a way to limit ajax request (Simperfit)
* bug #26088 [FrameworkBundle] Fix using annotation_reader in compiler pass to inject configured cache provider (Laizerox)
* bug #26157 [HttpKernel] Send new session cookie from AbstractTestSessionListener after session invalidation (rpkamp)
* bug #26230 [WebProfilerBundle] Fix anchor CSS (ro0NL)
* bug #26228 [HttpFoundation] Fix missing "throw" in JsonResponse (nicolas-grekas)
* bug #26211 [Console] Suppress warning from sapi_windows_vt100_support (adawolfa)
* bug #26176 Retro-fit proxy code to make it deterministic for older proxy manager implementations (lstrojny)
* bug #25787 Yaml parser regression with comments and non-strings (alexpott)
* bug #26156 Fixes #26136: Avoid emitting warning in hasParameterOption() (greg-1-anderson)
* bug #26183 [DI] Add null check for removeChild (changmin.keum)
* bug #26167 [TwigBridge] Apply some changes to support Bootstrap4-stable (mpiot, Nyholm)
* bug #26173 [Security] fix accessing request values (xabbuh)
* bug #26089 [PhpUnitBridge] Added support for PHPUnit 7 in Coverage Listener (lyrixx)
* bug #26170 [PHPUnit bridge] Avoid running the remove command without any packages (stof)
* bug #26159 created validator.tl.xlf for Form/Translations (ergiegonzaga)
* bug #26100 [Routing] Throw 405 instead of 404 when redirect is not possible (nicolas-grekas)
* bug #26119 [TwigBundle][WebProfilerBundle] Fix JS collision (ro0NL)
* bug #26040 [Process] Check PHP_BINDIR before $PATH in PhpExecutableFinder (nicolas-grekas)
* bug #26067 [YAML] Issue #26065: leading spaces in YAML multi-line string literals (tamc)
* bug #26012 Exit as late as possible (greg0ire)
* bug #26082 [Cache][WebProfiler] fix collecting cache stats with sub-requests + allow clearing calls (dmaicher)
* bug #26024 [PhpBridge] add PHPUnit 7 support to SymfonyTestsListener (shieldo)
* bug #26020 [Lock] Log already-locked errors as "notice" instead of "warning" (Simperfit)
* bug #26043 [Serialized] add context to serialize and deserialize (andrey1s)
* bug #26127 Deterministic time in cache items for reproducible builds (lstrojny)
* bug #26128 Make kernel build time optionally deterministic (lstrojny)
* bug #26117 isCsrfTokenValid() replace string by ?string (GaylordP)
* bug #26112 Env var maps to undefined constant. (dsmink)
* bug #26111 [Security] fix merge of 2.7 into 2.8 + add test case (dmaicher)
* bug #25893 [Console] Fix hasParameterOption / getParameterOption when used with multiple flags (greg-1-anderson)
* bug #25756 [TwigBundle] Register TwigBridge extensions first (fancyweb)
* bug #26051 [WebProfilerBundle] Fix sub request link (ro0NL)
* bug #25947 PhpDocExtractor::getTypes() throws fatal error when type omitted (Jared Farrish)
* bug #25940 [Form] keep the context when validating forms (xabbuh)
* bug #26057 [SecurityBundle] use libsodium to run Argon2i related tests (xabbuh)
* bug #25373 Use the PCRE_DOLLAR_ENDONLY modifier in route regexes (mpdude)
* bug #24435 [Form] Make sure errors are a part of the label on bootstrap 4 - this is a requirement for WCAG2 (Nyholm)
* bug #25762 [DependencyInjection] always call the parent class' constructor (xabbuh)
* bug #25976 [Config] Handle Service/EventSubscriberInterface in ReflectionClassResource (nicolas-grekas)
* bug #25989 [DI][Routing] Fix tracking of globbed resources (nicolas-grekas, sroze)
* bug #26009 [SecurityBundle] Allow remember-me factory creation when multiple user providers are configured. (iisisrael)
* bug #26010 [CssSelector] For AND operator, the left operand should have parentheses, not only right operand (Arnaud CHASSEUX)
* bug #26000 Fixed issue #25985 (KevinFrantz)
* bug #25996 Don't show wanna-be-private services as public in debug:container (chalasr)
* bug #25914 [HttpKernel] collect extension information as late as possible (xabbuh)
* bug #25981 [DI] Fix tracking of source class changes for lazy-proxies (nicolas-grekas)
* bug #25971 [Debug] Fix bad registration of exception handler, leading to mem leak (nicolas-grekas)
* bug #25962 [Routing] Fix trailing slash redirection for non-safe verbs (nicolas-grekas)
* bug #25948 [Form] Fixed empty data on expanded ChoiceType and FileType (HeahDude)
* bug #25978 Deterministic proxy names (lstrojny)
* bug #25972 support sapi_windows_vt100_support for php 7.2+ (jhdxr)
* bug #25744 [TwigBridge] Allow label translation to be safe (MatTheCat)
* bug #25932 Don't stop PSR-4 service discovery if a parent class is missing (derrabus)
* 4.0.4 (2018-01-29)
* bug #25922 [HttpFoundation] Use the correct syntax for session gc based on Pdo driver (tanasecosminromeo)
* bug #25933 Disable CSP header on exception pages only in debug (ostrolucky)
* bug #25926 [Form] Fixed Button::setParent() when already submitted (HeahDude)
* bug #25927 [Form] Fixed submitting disabled buttons (HeahDude)
* bug #25397 [Console] Provide a DX where an array could be passed (Simperfit)
* bug #25858 [DI] Fix initialization of legacy containers by delaying include_once (nicolas-grekas)
* bug #25891 [DependencyInjection] allow null values for root nodes in YAML configs (xabbuh)
* bug #24864 Have weak_vendors ignore deprecations from outside (greg0ire)
* bug #25873 [Console] Fix using finally where the catch can also fail (nicolas-grekas)
* bug #25848 [Validator] add missing parent isset and add test (Simperfit)
* bug #25869 [Process] Skip environment variables with false value in Process (francoispluchino)
* bug #25864 [Yaml] don't split lines on carriage returns when dumping (xabbuh)
* bug #25863 [Yaml] trim spaces from unquoted scalar values (xabbuh)
* bug #25861 do not conflict with egulias/email-validator 2.0+ (xabbuh)
* bug #25851 [Validator] Conflict with egulias/email-validator 2.0 (emodric)
* bug #25837 [SecurityBundle] Don't register in memory users as services (chalasr)
* bug #25835 [HttpKernel] DebugHandlersListener should always replace the existing exception handler (nicolas-grekas)
* bug #25829 [Debug] Always decorate existing exception handlers to deal with fatal errors (nicolas-grekas)
* bug #25823 [Security] Notify that symfony/expression-language is not installed if ExpressionLanguage is used (giovannialbero1992)
* bug #25824 Fixing a bug where the dump() function depended on bundle ordering (weaverryan)
* bug #25763 [OptionsResolver] Fix options resolver with array allowed types (mcg-web)
* bug #25789 Enableable ArrayNodeDefinition is disabled for empty configuration (kejwmen)
* bug #25822 [Cache] Fix handling of apcu_fetch() edgy behavior (nicolas-grekas)
* bug #25816 Problem in phar see mergerequest #25579 (betzholz)
* bug #25781 [Form] Disallow transform dates beyond the year 9999 (curry684)
* bug #25287 [Serializer] DateTimeNormalizer handling of null and empty values (returning it instead of new object) (Simperfit)
* bug #25249 [Form] Avoid button label translation when it's set to false (TeLiXj)
* bug #25127 [TwigBridge] Pass the form-check-inline in parent (Simperfit)
* bug #25812 Copied NO language files to the new NB locale (derrabus)
* bug #25753 [Console] Fix restoring exception handler (nicolas-grekas, fancyweb)
* bug #25801 [Router] Skip anonymous classes when loading annotated routes (pierredup)
* bug #25508 [FrameworkBundle] Auto-enable CSRF if the component *+ session* are loaded (nicolas-grekas)
* bug #25657 [Security] Fix fatal error on non string username (chalasr)
* bug #25791 [Routing] Make sure we only build routes once (sroze)
* bug #25799 Fixed Request::__toString ignoring cookies (Toflar)
* bug #25755 [Debug] prevent infinite loop with faulty exception handlers (nicolas-grekas)
* bug #25771 [Validator] 19 digits VISA card numbers are valid (xabbuh)
* bug #25751 [FrameworkBundle] Add the missing `enabled` session attribute (sroze)
* bug #25750 [HttpKernel] Turn bad hosts into 400 instead of 500 (nicolas-grekas)
* bug #25699 [HttpKernel] Fix session handling: decouple "save" from setting response "private" (nicolas-grekas)
* bug #25490 [Serializer] Fixed throwing exception with option JSON_PARTIAL_OUTPUT_ON_ERROR (diversantvlz)
* bug #25737 [TwigBridge] swap filter/function and package names (xabbuh)
* bug #25731 [HttpFoundation] Always call proxied handler::destroy() in StrictSessionHandler (nicolas-grekas)
* bug #25733 [HttpKernel] Fix compile error when a legacy container is fresh again (nicolas-grekas)
* bug #25709 Tweaked some styles in the profiler tables (javiereguiluz)
* bug #25719 [HttpKernel] Uses cookies to track the requests redirection (sroze)
* bug #25696 [FrameworkBundle] Fix using "annotations.cached_reader" in after-removing passes (nicolas-grekas)
* feature #25669 [Security] Fail gracefully if the security token cannot be unserialized from the session (thewilkybarkid)
* bug #25700 Run simple-phpunit with --no-suggest option (ro0NL)
* 4.0.3 (2018-01-05)
* bug #25685 Use triggering file to determine weak vendors if when the test is run in a separate process (alexpott)
* bug #25671 Remove randomness from dumped containers (nicolas-grekas)
* bug #25532 [HttpKernel] Disable CSP header on exception pages (ostrolucky)
* bug #25678 [WebProfilerBundle] set the var in the right scope (Jochen Mandl)
* bug #25491 [Routing] Use the default host even if context is empty (sroze)
* bug #25672 [WebServerBundle] use interface_exists instead of class_exists (kbond)
* bug #25662 Dumper shouldn't use html format for phpdbg / cli-server (jhoff)
* bug #25529 [Validator] Fix access to root object when using composite constraint (ostrolucky)
* bug #25404 [Form] Remove group options without data on debug:form command (yceruto)
* bug #25430 Fixes for Oracle in PdoSessionHandler (elislenio)
* bug #25117 [FrameworkBundle] Make cache:clear "atomic" and consistent with cache:warmup (hkdobrev)
* bug #25583 [HttpKernel] Call Response->setPrivate() instead of sending raw header() when session is started (Toflar)
* bug #25601 [TwigBundle/Brige] catch missing requirements to throw meaningful exceptions (nicolas-grekas)
* bug #25547 [DX][DependencyInjection] Suggest to write an implementation if the interface cannot be autowired (sroze)
* bug #25599 Add application/ld+json format associated to json (vincentchalamon)
* bug #25623 [HttpFoundation] Fix false-positive ConflictingHeadersException (nicolas-grekas)
* bug #25624 [WebServerBundle] Fix escaping of php binary with arguments (nicolas-grekas)
* bug #25604 Add check for SecurityBundle in createAccessDeniedException (FGM)
* bug #25591 [HttpKernel] fix cleaning legacy containers (nicolas-grekas)
* bug #25526 [WebProfilerBundle] Fix panel break when stopwatch component is not installed. (umulmrum, javiereguiluz)
* bug #25606 Updating message to inform the user how to install the component (weaverryan)
* bug #25571 [SecurityBundle] allow auto_wire for SessionAuthenticationStrategy class (xavren)
* bug #25567 [Process] Fix setting empty env vars (nicolas-grekas)
* bug #25407 [Console] Commands with an alias should not be recognized as ambiguous (Simperfit)
* bug #25523 [WebServerBundle] fix a bug where require would not require the good file because of env (Simperfit)
* bug #25559 [Process] Dont use getenv(), it returns arrays and can introduce subtle breaks accros PHP versions (nicolas-grekas)
* bug #25552 [WebProfilerBundle] Let fetch() cast URL to string (ro0NL)
* bug #25521 [Console] fix a bug when you are passing a default value and passing -n would output the index (Simperfit)
* 4.0.2 (2017-12-15)
* bug #25489 [FrameworkBundle] remove esi/ssi renderers if inactive (dmaicher)
* bug #25502 Fixing wrong class_exists on interface (weaverryan)
* bug #25427 Preserve percent-encoding in URLs when performing redirects in the UrlMatcher (mpdude)
* bug #25480 [FrameworkBundle] add missing validation options to XSD file (xabbuh)
* bug #25487 [Console] Fix a bug when passing a letter that could be an alias (Simperfit)
* bug #25425 When available use AnnotationRegistry::registerUniqueLoader (jrjohnson)
* bug #25474 [DI] Optimize Container::get() for perf (nicolas-grekas)
* bug #24594 [Translation] Fix InvalidArgumentException when using untranslated plural forms from .po files (BjornTwachtmann)
* bug #25233 [TwigBridge][Form] Fix hidden currency element with Bootstrap 3 theme (julienfalque)
* bug #25413 [HttpKernel] detect deprecations thrown by container initialization during tests (nicolas-grekas)
* bug #25408 [Debug] Fix catching fatal errors in case of nested error handlers (nicolas-grekas)
* bug #25330 [HttpFoundation] Support 0 bit netmask in IPv6 (`::/0`) (stephank)
* bug #25378 [VarDumper] Fixed file links leave blank pages when ide is configured (antalaron)
* bug #25410 [HttpKernel] Fix logging of post-terminate errors/exceptions (nicolas-grekas)
* bug #25409 [Bridge/Doctrine] Drop "memcache" type (nicolas-grekas)
* bug #25417 [Process] Dont rely on putenv(), it fails on ZTS PHP (nicolas-grekas)
* bug #25333 [DI] Impossible to set an environment variable and then an array as container parameter (Phantas0s)
* bug #25447 [Process] remove false-positive BC breaking exception on Windows (nicolas-grekas)
* bug #25381 [DI] Add context to service-not-found exceptions thrown by service locators (nicolas-grekas)
* bug #25438 [Yaml] empty lines don't count for indent detection (xabbuh)
* bug #25412 Extend Argon2i support check to account for sodium_compat (mbabker)
* bug #25392 [HttpFoundation] Fixed default user-agent (3.X -> 4.X) (lyrixx)
* bug #25389 [Yaml] fix some edge cases with indented blocks (xabbuh)
* bug #25396 [Form] Fix debug:form command definition (yceruto)
* bug #25398 [HttpFoundation] don't prefix cookies with "Set-Cookie:" (pableu)
* bug #25354 [DI] Fix non-string class handling in PhpDumper (nicolas-grekas, sroze)
* bug #25340 [Serializer] Unset attributes when creating child context (dunglas)
* bug #25325 [Yaml] do not evaluate PHP constant names (xabbuh)
* bug #25380 [FrameworkBundle][Cache] register system cache clearer only if it's used (xabbuh)
* bug #25323 [ExpressionLanguage] throw an SyntaxError instead of an undefined index notice (Simperfit)
* bug #25363 [HttpKernel] Disable inlining on PHP 5 (nicolas-grekas)
* bug #25364 [DependencyInjection] Prevent a loop in aliases within the `findDefinition` method (sroze)
* bug #25337 Remove Exclusive Lock That Breaks NFS Caching (brianfreytag)
* 4.0.1 (2017-12-05)
* bug #25304 [Bridge/PhpUnit] Prefer $_SERVER['argv'] over $argv (ricknox)
* bug #25272 [SecurityBundle] fix setLogoutOnUserChange calls for context listeners (dmaicher)
* bug #25282 [DI] Register singly-implemented interfaces when doing PSR-4 discovery (nicolas-grekas)
* bug #25274 [Security] Adding a GuardAuthenticatorHandler alias (weaverryan)
* bug #25308 [FrameworkBundle] Fix a bug where a color tag will be shown when passing an antislash (Simperfit)
* bug #25278 Fix for missing whitespace control modifier in form layout (kubawerlos)
* bug #25306 [Form][TwigBridge] Fix collision between view properties and form fields (yceruto)
* bug #25305 [Form][TwigBridge] Fix collision between view properties and form fields (yceruto)
* bug #25236 [Form][TwigBridge] Fix collision between view properties and form fields (yceruto)
* bug #25312 [DI] Fix deep-inlining of non-shared refs (nicolas-grekas)
* bug #25309 [Yaml] parse newlines in quoted multiline strings (xabbuh)
* bug #25313 [DI] Fix missing unset leading to false-positive circular ref (nicolas-grekas)
* bug #25268 [DI] turn $private to protected in dumped container, to make cache:clear BC (nicolas-grekas)
* bug #25285 [DI] Throw an exception if Expression Language is not installed (sroze)
* bug #25241 [Yaml] do not eagerly filter comment lines (xabbuh)
* bug #25284 [DI] Cast ids to string, as done on 3.4 (nicolas-grekas, sroze)
* bug #25297 [Validator] Fixed the @Valid(groups={"group"}) against null exception case (vudaltsov)
* bug #25255 [Console][DI] Fail gracefully (nicolas-grekas)
* bug #25264 [DI] Trigger deprecation when setting a to-be-private synthetic service (nicolas-grekas)
* bug #25258 [link] Prevent warnings when running link with 2.7 (dunglas)
* bug #25244 [DI] Add missing deprecation when fetching private services from ContainerBuilder (nicolas-grekas)
* bug #24750 [Validator] ExpressionValidator should use OBJECT_TO_STRING (Simperfit)
* bug #25247 [DI] Fix false-positive circular exception (nicolas-grekas)
* bug #25226 [HttpKernel] Fix issue when resetting DumpDataCollector (Pierstoval)
* bug #25230 Use a more specific file for detecting the bridge (greg0ire)
* bug #25232 [WebProfilerBundle] [TwigBundle] Fix Profiler breaking XHTML pages (tistre)
* 4.0.0 (2017-11-30)
* bug #25220 [HttpFoundation] Add Session::isEmpty(), fix MockFileSessionStorage to behave like the native one (nicolas-grekas)
* bug #25209 [VarDumper] Dont use empty(), it chokes on eg GMP objects (nicolas-grekas)
* bug #25200 [HttpKernel] Arrays with scalar values passed to ESI fragment renderer throw deprecation notice (Simperfit)
* bug #25201 [HttpKernel] Add a better error messages when passing a private or non-tagged controller (Simperfit)
* bug #25155 [DependencyInjection] Detect case mismatch in autowiring (Simperfit, sroze)
* bug #25217 [Dotenv] Changed preg_match flags from null to 0 (deekthesqueak)
* bug #25180 [DI] Fix circular reference when using setters (nicolas-grekas)
* bug #25204 [DI] Clear service reference graph (nicolas-grekas)
* bug #25203 [DI] Fix infinite loop in InlineServiceDefinitionsPass (nicolas-grekas)
* bug #25185 [Serializer] Do not cache attributes if `attributes` in context (sroze)
* bug #25190 [HttpKernel] Keep legacy container files for concurrent requests (nicolas-grekas)
* bug #25182 [HttpFoundation] AutExpireFlashBag should not clear new flashes (Simperfit, sroze)
* bug #25174 [Translation] modify definitions only if the do exist (xabbuh)
* bug #25179 [FrameworkBundle][Serializer] Remove YamlEncoder definition if Yaml component isn't installed (ogizanagi)
* bug #25160 [DI] Prevent a ReflectionException during cache:clear when the parent class doesn't exist (dunglas)
* bug #25163 [DI] Fix tracking of env vars in exceptions (nicolas-grekas)
* bug #25162 [HttpKernel] Read $_ENV when checking SHELL_VERBOSITY (nicolas-grekas)
* bug #25158 [DI] Remove unreachable code (GawainLynch)
* bug #25152 [Form] Don't rely on `Symfony\Component\HttpFoundation\File\File` if http-foundation isn't in FileType (issei-m)
* bug #24987 [Console] Fix global console flag when used in chain (Simperfit)
* bug #25137 Adding checks for the expression language (weaverryan)
* bug #25151 [FrameworkBundle] Automatically enable the CSRF protection if CSRF manager exists (sroze)
* bug #25043 [Yaml] added ability for substitute aliases when mapping is on single line (Michał Strzelecki, xabbuh)
* 4.0.0-RC2 (2017-11-24)
* bug #25146 [DI] Dont resolve envs in service ids (nicolas-grekas)
* bug #25113 [Routing] Fix "config-file-relative" annotation loader resources (nicolas-grekas, sroze)
* bug #25065 [FrameworkBundle] Update translation commands to work with default paths (yceruto)
* bug #25109 Make debug:container search command case-insensitive (jzawadzki)
* bug #25121 [FrameworkBundle] Fix AssetsInstallCommand (nicolas-grekas)
* bug #25102 [Form] Fixed ContextErrorException in FileType (chihiro-adachi)
* bug #25130 [DI] Fix handling of inlined definitions by ContainerBuilder (nicolas-grekas)
* bug #25119 [DI] Fix infinite loop when analyzing references (nicolas-grekas)
* bug #25094 [FrameworkBundle][DX] Display a nice error message if an enabled component is missing (derrabus)
* bug #25100 [SecurityBundle] providerIds is undefined error when firewall provider is not specified (karser)
* bug #25100 [SecurityBundle] providerIds is undefined error when firewall provider is not specified (karser)
* bug #25100 [SecurityBundle] providerIds is undefined error when firewall provider is not specified (karser)
* bug #25097 [Bridge\PhpUnit] Turn "preserveGlobalState" to false by default, revert "Blacklist" removal (nicolas-grekas)
* 4.0.0-RC1 (2017-11-21)
* bug #25077 [Bridge/Twig] Let getFlashes starts the session (MatTheCat)
* bug #25082 [HttpKernel] Disable container inlining when legacy inlining has been used (nicolas-grekas)
* bug #25022 [Filesystem] Updated Filesystem::makePathRelative (inso)
* bug #25072 [Bridge/PhpUnit] Remove trailing "\n" from ClockMock::microtime(false) (joky)
* bug #25069 [Debug] Fix undefined variable $lightTrace (nicolas-grekas)
* bug #25053 [Serializer] Fixing PropertyNormalizer supports parent properties (Christopher Hertel)
* bug #25055 [DI] Analyze setter-circular deps more precisely (nicolas-grekas)
* feature #25056 [Bridge/PhpUnit] Sync the bridge version installed in vendor/ and in phpunit clone (nicolas-grekas)
* bug #25048 Allow EnumNode name to be null (MatTheCat)
* bug #25045 [SecurityBundle] Don't trigger auto-picking notice if provider is set per listener (chalasr)
* bug #25033 [FrameworkBundle] Dont create empty bundles directory by default (ro0NL)
* bug #25037 [DI] Skip hot_path tag for deprecated services as their class might also be (nicolas-grekas)
* bug #25038 [Cache] Memcached options should ignore "lazy" (nicolas-grekas)
* bug #25014 Move deprecation under use statements (greg0ire)
* bug #25030 [Console] Fix ability to disable lazy commands (chalasr)
* bug #25032 [Bridge\PhpUnit] Disable broken auto-require mechanism of phpunit (nicolas-grekas)
* bug #25016 [HttpKernel] add type-hint for the requestType (Simperfit)
* bug #25027 [FrameworkBundle] Hide server:log command based on deps (sroze)
* bug #24991 [DependencyInjection] Single typed argument can be applied on multiple parameters (nicolas-grekas, sroze)
* bug #24983 [Validator] enter the context in which to validate (xabbuh)
* bug #24956 Fix ambiguous pattern (weltling)
* bug #24732 [DependencyInjection] Prevent service:method factory notation in PHP config (vudaltsov)
* bug #24979 [HttpKernel] remove services resetter even when it's an alias (xabbuh)
* bug #24972 [HttpKernel] Fix service arg resolver for controllers as array callables (sroze, nicolas-grekas)
* bug #24971 [FrameworkBundle] Empty event dispatcher earlier in CacheClearCommand (nicolas-grekas)
* security #24995 Validate redirect targets using the session cookie domain (nicolas-grekas)
* security #24994 Prevent bundle readers from breaking out of paths (xabbuh)
* security #24993 Ensure that submitted data are uploaded files (xabbuh)
* security #24992 Namespace generated CSRF tokens depending of the current scheme (dunglas)
* bug #24975 [DomCrawler] Type fix Crawler:: discoverNamespace() (VolCh)
* bug #24954 [DI] Fix dumping with custom base class (nicolas-grekas)
* bug #24952 [HttpFoundation] Fix session-related BC break (nicolas-grekas, sroze)
* bug #24943 [FrameworkBundle] Wire the translation.reader service instead of deprecated translation.loader in commands (ogizanagi)
* 4.0.0-BETA4 (2017-11-12)
* bug #24874 [TwigBridge] Fixed the .form-check-input class in the bs4 templates (vudaltsov)
* bug #24929 [Console] Fix traversable autocomplete values (ro0NL)
* feature #24860 [FrameworkBundle] Add default translations path option and convention (yceruto)
* bug #24921 [Debug] Remove false-positive deprecation from DebugClassLoader (nicolas-grekas)
* bug #24856 [FrameworkBundle] Add default mapping path for validator component in bundle-less app (yceruto)
* bug #24833 [FrameworkBundle] Add default mapping path for serializer component in bundle-less app (yceruto)
* bug #24908 [WebServerBundle] Prevent console.terminate from being fired when server:start finishes (kbond)
* bug #24888 [FrameworkBundle] Specifically inject the debug dispatcher in the collector (ogizanagi)
* bug #24909 [Intl] Update ICU data to 60.1 (jakzal)
* bug #24870 [YAML] Allow to parse custom tags when linting yaml files (pierredup)
* bug #24910 [HttpKernel][Debug] Remove noise from stack frames of deprecations (nicolas-grekas)
* bug #24906 [Bridge/ProxyManager] Remove direct reference to value holder property (nicolas-grekas)
* feature #24887 [Cache][Lock] Add RedisProxy for lazy Redis connections (nicolas-grekas)
* bug #24633 [Config] Fix cannotBeEmpty() (ro0NL)
* bug #24900 [Validator] Fix Costa Rica IBAN format (Bozhidar Hristov)
* bug #24904 [Validator] Add Belarus IBAN format (Bozhidar Hristov)
* bug #24837 [TwigBridge] [Bootstrap 4] Fix validation error design for expanded choiceType (ostrolucky)
* bug #24878 [HttpFoundation] Prevent PHP from sending Last-Modified on session start (nicolas-grekas)
* bug #24881 [WebserverBundle] fixed the bug that caused that the webserver would … (Serkan Yildiz)
* bug #24722 Replace more docblocks by type-hints (nicolas-grekas)
* bug #24850 [DI] Fix cannot bind env var (ogizanagi)
* bug #24851 [TwigBridge] Fix BC break due required twig environment (ro0NL)
* 4.0.0-BETA3 (2017-11-05)
* bug #24531 [HttpFoundation] Fix forward-compat of NativeSessionStorage with PHP 7.2 (sroze)
* bug #24828 [DI] Fix the "almost-circular refs" fix (nicolas-grekas)
* bug #24665 Fix dump panel hidden when closing a dump (julienfalque)
* bug #24802 [TwigBridge] [Bootstrap 4] Fix hidden errors (ostrolucky)
* bug #24816 [Serializer] Fix extra attributes when no group specified (ogizanagi)
* bug #24822 [DI] Fix "almost-circular" dependencies handling (nicolas-grekas)
* bug #24821 symfony/form auto-enables symfony/validator, even when not present (weaverryan)
* bug #24824 [FrameworkBundle][Config] fix: do not add resource checkers for no-debug (dmaicher)
* bug #24814 [Intl] Make intl-data tests pass and save language aliases again (jakzal)
* bug #24810 [Serializer] readd default argument value (xabbuh)
* bug #24809 [Config] Fix dump of config references for deprecated nodes (chalasr)
* bug #24796 [PhpUnitBridge] Fixed fatal error in CoverageListener when something goes wrong in Test::setUpBeforeClass (lyrixx)
* bug #24774 [HttpKernel] Let the storage manage the session starts (sroze)
* bug #24735 [VarDumper] fix trailling comma when dumping an exception (Simperfit)
* bug #24770 [Validator] Fix TraceableValidator is reset on data collector instantiation (ogizanagi)
* bug #24764 [HttpFoundation] add Early Hints to Reponse to fix test (Simperfit)
* bug #24759 Removes \n or space when $context/$extra are empty (kirkmadera)
* bug #24758 Throwing exception if redis and predis unavailable (aequasi)
* 4.0.0-BETA2 (2017-10-30)
* bug #24728 [Bridge\Twig] fix bootstrap checkbox_row to render properly & remove spaceless (arkste)
* bug #24709 [HttpKernel] Move services reset to Kernel::handle()+boot() (nicolas-grekas)
* bug #24703 [TwigBridge] Bootstrap 4 form theme fixes (vudaltsov)
* bug #24744 debug:container --types: Fix bug with non-existent classes (weaverryan)
* bug #24747 [VarDumper] HtmlDumper: fix collapsing nodes with depth < maxDepth (ogizanagi)
* bug #24743 [FrameworkBundle] Do not activate the cache if Doctrine's cache is not present (sroze)
* bug #24605 [FrameworkBundle] Do not load property_access.xml if the component isn't installed (ogizanagi)
* bug #24710 [TwigBridge] Fix template paths in profiler (ro0NL)
* bug #24706 [DependencyInjection] Add the possibility to disable assets via xml (renatomefi)
* bug #24696 Ensure DeprecationErrorHandler::collectDeprecations() is triggered (alexpott)
* bug #24711 [TwigBridge] Re-add Bootstrap 3 Checkbox Layout (arkste)
* bug #24713 [FrameworkBundle] fix CachePoolPrunerPass to use correct command service id (kbond)
* bug #24686 Fix $_ENV/$_SERVER precedence in test framework (fabpot)
* bug #24691 [HttpFoundation] Fix caching of session-enabled pages (nicolas-grekas)
* feature #24677 [HttpFoundation] Allow DateTimeImmutable in Response setters (derrabus)
* bug #24694 [Intl] Allow passing null as a locale fallback (jakzal)
* bug #24606 [HttpFoundation] Fix FileBag issue with associative arrays (enumag)
* bug #24673 [DI] Throw when a service name or an alias contains dynamic values (prevent an infinite loop) (dunglas)
* bug #24684 [Security] remove invalid deprecation notice on AbstractGuardAuthenticator::supports() (kbond)
* bug #24681 Fix isolated error handling (alexpott)
* bug #24575 Ensure that PHPUnit's error handler is still working in isolated tests (alexpott)
* bug #24597 [PhpUnitBridge] fix deprecation triggering test detection (xabbuh)
* feature #24671 [DI] Handle container.autowiring.strict_mode to opt-out from legacy autowiring (nicolas-grekas)
* bug #24660 Escape trailing \ in QuestionHelper autocompletion (kamazee)
* bug #24624 [Security] Fix missing BC layer for AbstractGuardAuthenticator::getCredentials() (chalasr)
* bug #24598 Prefer line formatter on missing cli dumper (greg0ire)
* bug #24635 [DI] Register default env var provided types (ro0NL)
* bug #24620 [FrameworkBundle][Workflow] Fix deprectation when checking workflow.registry service in dump command (Jean-Beru)
* bug #24644 [Security] Fixed auth provider authenticate() cannot return void (glye)
* bug #24642 [Routing] Fix resource miss (dunglas)
* bug #24608 Adding the Form default theme files to be warmed up in Twig's cache (weaverryan)
* bug #24626 streamed response should return $this (DQNEO)
* feature #24631 [Form] Fix FormEvents::* constant and value matching (yceruto, javiereguiluz)
* bug #24630 [WebServerBundle] Prevent commands from being registered by convention (chalasr)
* bug #24589 Username and password in basic auth are allowed to contain '.' (Richard Quadling)
* bug #24566 Fixed unsetting from loosely equal keys OrderedHashMap (maryo)
* bug #24570 [Debug] Fix same vendor detection in class loader (Jean-Beru)
* bug #24573 Fixed pathinfo calculation for requests starting with a question mark. (syzygymsu)
* bug #24565 [Serializer] YamlEncoder: throw if the Yaml component isn't installed (dunglas)
* bug #24563 [Serializer] ObjectNormalizer: throw if PropertyAccess isn't installed (dunglas)
* bug #24571 [PropertyInfo] Add support for the iterable type (dunglas)
* bug #24579 pdo session fix (mxp100)
* bug #24536 [Security] Reject remember-me token if UserCheckerInterface::checkPostAuth() fails (kbond)
* 4.0.0-BETA1 (2017-10-19)
* feature #24583 Adding a new debug:autowiring command (weaverryan)
* feature #24523 [HttpFoundation] Make sessions secure and lazy (nicolas-grekas)
* feature #22610 [Form] [TwigBridge] Added option to disable usage of default themes when rendering a form (emodric)
* feature #23112 [OptionsResolver] Support array of types in allowed type (pierredup)
* feature #24321 added ability to handle parent classes for PropertyNormalizer (ivoba)
* feature #24505 [HttpKernel] implement reset() in DumpDataCollector (xabbuh)
* feature #24425 [Console][HttpKernel] Handle new SHELL_VERBOSITY env var, also configures the default logger (nicolas-grekas)
* feature #24503 [MonologBridge][EventDispatcher][HttpKernel] remove deprecated features (xabbuh)
* feature #24387 [FORM] Prevent forms from extending itself as a parent (pierredup)
* feature #24484 [DI] Throw accurate failures when accessing removed services (nicolas-grekas)
* feature #24208 [Form] Display option definition from a given form type (yceruto, ogizanagi)
* feature #22228 [HttpKernel] minor: add ability to construct with headers on http exceptions (gsdevme)
* feature #24467 [Process] drop non-existent working directory support (xabbuh)
* feature #23499 [Workflow] add guard is_valid() method support (alain-flaus, lyrixx)
* feature #24364 [DependencyInjection][Filesystem][Security][SecurityBundle] remove deprecated features (xabbuh)
* feature #24441 [Bridge\Doctrine][FrameworkBundle] Remove legacy uses of ContainerAwareInterface (nicolas-grekas)
* feature #24388 [Security] Look at headers for switch_user username (chalasr)
* feature #24447 [Session] remove deprecated session handlers (Tobion)
* feature #24446 [Security] Remove GuardAuthenticatorInterface (chalasr)
* feature #23708 Added deprecation to cwd not existing Fixes #18249 (alexbowers)
* feature #24443 [Session] deprecate MemcacheSessionHandler (Tobion)
* feature #24409 [Bridge\Doctrine][FrameworkBundle] Deprecate some remaining uses of ContainerAwareTrait (nicolas-grekas)
* feature #24438 [Session][VarDumper] Deprecate accepting legacy mongo extension (Tobion)
* feature #24389 [DoctrineBridge] Deprecate dbal session handler (Tobion)
* feature #16835 [Security] Add Guard authenticator <supports> method (Amo, chalasr)
* feature #24289 [FrameworkBundle][HttpKernel] Reset profiler (derrabus)
* feature #24144 [FrameworkBundle] Expose dotenv in bin/console about (ro0NL)
* feature #24403 [FrameworkBundle][Routing] Show welcome message if no routes are configured (yceruto)
* feature #24398 [DI] Remove AutowireExceptionPass (ogizanagi)
* feature #22679 [Form] Add tel and color types (apetitpa)
* feature #23845 [Validator] Add unique entity violation cause (Ilya Vertakov)
* feature #22132 [Lock] Automaticaly release lock when user forget it (jderusse)
* feature #21751 Bootstrap4 support for Twig form theme (hiddewie, javiereguiluz)
* feature #24383 [FrameworkBundle] Don't clear app pools on cache:clear (nicolas-grekas)
* feature #24148 [Form] Hide label button when its setted to false (TeLiXj)
* feature #24380 [SecurityBundle] Remove auto picking the first provider (ogizanagi)
* feature #24378 [SecurityBundle] Deprecate auto picking the first provider (ogizanagi)
* feature #24260 [Security] Add impersonation support for stateless authentication (chalasr)
* feature #24300 [HttpKernel][FrameworkBundle] Add a minimalist default PSR-3 logger (dunglas)
* feature #21604 [Security] Argon2i Password Encoder (zanbaldwin)
* feature #24372 [DowCrawler] Default to UTF-8 when possible (nicolas-grekas)
* feature #24264 [TwigBundle] Improve the overriding of bundle templates (yceruto)
* feature #24197 [Translation] Moved PhpExtractor and PhpStringTokenParser to Translation component (Nyholm)
* feature #24362 [HttpKernel] Deprecate some compiler passes in favor of tagged iterator args (nicolas-grekas)
* feature #21027 [Asset] Provide default context (ro0NL)
* feature #22200 [DI] Reference tagged services in config (ro0NL)
* feature #24337 Adding a shortcuts for the main security functionality (weaverryan, javiereguiluz)
* feature #24358 [TwigBundle] register an identity translator as fallback (xabbuh)
* feature #24357 [Yaml] include file and line no in deprecation message (xabbuh)
* feature #24330 [FrameworkBundle] register class metadata factory alias (xabbuh)
* feature #24348 [SecurityBundle] Remove remaining ACL stuff from SecurityBundle (ogizanagi)
* feature #24349 [SecurityBundle] Add missing AclSchemaListener deprecation (ogizanagi)
* feature #24202 [Filesystem] deprecate relative paths in makePathRelative() (xabbuh)
* feature #21716 [Serializer] Add Support for `object_to_populate` in CustomNormalizer (chrisguitarguy)
* feature #21960 Remove Validator\TypeTestCase and add validator logic to base TypeTestCase (pierredup)
* feature #24338 [HttpFoundation] Removed compatibility layer for PHP <5.4 sessions (afurculita)
* feature #22113 [Lock] Include lock component in framework bundle (jderusse)
* feature #24236 [WebProfilerBundle] Render file links for twig templates (ro0NL)
* feature #21239 [Serializer] throw more specific exceptions (xabbuh)
* feature #24341 [SecurityBundle] Remove ACL related code (chalasr)
* feature #24256 CsvEncoder handling variable structures and custom header order (Oliver Hoff)
* feature #23471 [Finder] Add a method to check if any results were found (duncan3dc)
* feature #23149 [PhpUnitBridge] Added a CoverageListener to enhance the code coverage report (lyrixx)
* feature #24161 [HttpKernel] Remove bundle inheritance (fabpot)
* feature #24318 [SecurityBundle] Deprecate ACL related code (chalasr)
* feature #24335 [Security][SecurityBundle] Deprecate the HTTP digest auth (ogizanagi)
* feature #21951 [Security][Firewall] Passing the newly generated security token to the event during user switching (klandaika)
* feature #23485 [Config] extracted the xml parsing from XmlUtils::loadFile into XmlUtils::parse (Basster)
* feature #22890 [HttpKernel] Add ability to configure catching exceptions for Client (kbond)
* feature #24239 [HttpFoundation] Deprecate compatibility with PHP <5.4 sessions (afurculita)
* feature #23882 [Security] Deprecated not being logged out after user change (iltar)
* feature #24200 Added an alias for FlashBagInterface in config (tifabien)
* feature #24295 [DI][DX] Throw exception on some ContainerBuilder methods used from extensions (ogizanagi)
* feature #24253 [Yaml] support parsing files (xabbuh)
* feature #24290 Adding Definition::addError() and a compiler pass to throw errors as exceptions (weaverryan)
* feature #24301 [DI] Add AutowireRequiredMethodsPass to fix bindings for `@required` methods (nicolas-grekas)
* feature #24226 [Cache] Add ResettableInterface to allow resetting any pool's local state (nicolas-grekas)
* feature #24303 [FrameworkBundle] allow forms without translations and validator (xabbuh)
* feature #24291 [SecurityBundle] Reset the authentication token between requests (derrabus)
* feature #24280 [VarDumper] Make `dump()` a little bit more easier to use (freekmurze)
* feature #24277 [Serializer] Getter for extra attributes in ExtraAttributesException (mdeboer)
* feature #24257 [HttpKernel][DI] Enable Kernel to implement CompilerPassInterface (nicolas-grekas)
* feature #23834 [DI] Add "PHP fluent format" for configuring the container (nicolas-grekas)
* feature #24180 [Routing] Add PHP fluent DSL for configuring routes (nicolas-grekas)
* feature #24232 [Bridge\Doctrine] Add "DoctrineType::reset()" method (nicolas-grekas)
* feature #24238 [DI] Turn services and aliases private by default, with BC layer (nicolas-grekas)
* feature #24242 [Form] Remove deprecated ChoiceLoaderInterface implementation in TimezoneType (ogizanagi)
* feature #23648 [Form] Add input + regions options to TimezoneType (ro0NL)
* feature #24185 [Form] Display general forms information on debug:form (yceruto)
* feature #23747 [Serializer][FrameworkBundle] Add a DateInterval normalizer (Lctrs)
* feature #24193 [FrameworkBundle] Reset stopwatch between requests (derrabus)
* feature #24160 [HttpKernel] Deprecate bundle inheritance (fabpot)
* feature #24159 Remove the profiler.matcher configuration (fabpot)
* feature #24155 [FrameworkBundle][HttpKernel] Add DI tag for resettable services (derrabus)
* feature #23625 Feature #23583 Add current and fallback locales in WDT / Profiler (nemoneph)
* feature #24179 [TwigBundle] Add default templates directory and option to configure it (yceruto)
* feature #24176 [Translation] drop MessageSelector support in the Translator (xabbuh)
* feature #24104 Make as many services private as possible (nicolas-grekas)
* feature #18314 [Translation] added support for adding custom message formatter (aitboudad)
* feature #24158 deprecated profiler.matcher configuration (fabpot)
* feature #23728 [WebProfilerBundle] Removed the deprecated web_profiler.position option (javiereguiluz)
* feature #24131 [Console] Do not display short exception trace for common console exceptions (yceruto)
* feature #24080 Deprecated the web_profiler.position option (javiereguiluz)
* feature #24114 [SecurityBundle] Throw a meaningful exception when an undefined user provider is used inside a firewall (chalasr)
* feature #24122 [DI] rename ResolveDefinitionTemplatesPass to ResolveChildDefinitionsPass (nicolas-grekas)
* feature #23901 [DI] Allow processing env vars (nicolas-grekas)
* feature #24093 [FrameworkBundle] be able to enable workflow support explicitly (xabbuh)
* feature #24064 [TwigBridge] Show Twig's loader paths on debug:twig command (yceruto)
* feature #23978 [Cache] Use options from Memcached DSN (Bukashk0zzz)
* feature #24067 [HttpKernel] Dont register env parameter resource (ro0NL)
* feature #24075 Implemented PruneableInterface on TagAwareAdapter (Toflar)
* feature #23262 Add scalar typehints/return types (chalasr, xabbuh)
* feature #21414 [Console] Display file and line on Exception (arno14)
* feature #24068 [HttpKernel] Deprecate EnvParametersResource (ro0NL)
* feature #22542 [Lock] Check TTL expiration in lock acquisition (jderusse)
* feature #24031 [Routing] Add the possibility to define a prefix for all routes of a controller (fabpot)
* feature #24052 [DI] Remove case insensitive parameter names (ro0NL)
* feature #23967 [VarDumper] add force-collapse/expand + use it for traces (nicolas-grekas)
* feature #24033 [DI] Add ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE (nicolas-grekas)
* feature #24026 [Security] add impersonator_user to "User was reloaded" log message (gharlan)
* feature #24014 [Translator] Remove deprecated feature (maidmaid)
* feature #23603 [Cache] Add (pdo|chain) cache (adapter|simple) prune method (robfrawley)
* feature #23694 [Form] Add debug:form command (yceruto)
* feature #24028 [Yaml] mark some classes as final (xabbuh)
* feature #22543 [Lock] Expose an expiringDate and isExpired method in Lock (jderusse)
* feature #23667 [Translation] Create an TranslationReaderInterface and move TranslationLoader to TranslationComponent (Nyholm)
* feature #24024 [config] Add ability to deprecate a node (sanpii)
* feature #23668 [VarDumper] Add period caster (maidmaid)
* feature #23991 [DI] Improve psr4-based service discovery (alternative implementation) (kbond)
* feature #22382 [config] Add abbitily to deprecate a node (Nyholm, fabpot, sanpii)
* feature #23947 [Translation] Adding the ability do load <notes> in xliff2.0 (Nyholm)
* feature #23887 [Console] Allow commands to provide a default name for compile time registration (chalasr, nicolas-grekas)
* feature #23874 [DI] Case sensitive parameter names (ro0NL)
* feature #23936 Remove some sf2 references (fabpot)
* feature #23680 [Webprofiler] Added blocks that allows extension of the profiler page. (Nyholm)
* feature #23665 Create an interface for TranslationWriter (Nyholm)
* feature #23890 [Translation] Adding the ability do dump <notes> in xliff2.0 (Nyholm)
* feature #23862 [SecurityBundle] resolve class name parameter inside AddSecurityVotersPass (pjarmalavicius)
* feature #23915 [DI] Allow get available services from service locator (Koc)
* feature #23792 [HttpKernel][FrameworkBundle] Add RebootableInterface, fix and un-deprecate cache:clear with warmup (nicolas-grekas)
* feature #23227 Add support for "controller" keyword for configuring routes controllers (voronkovich)
* feature #23815 [FrameworkBundle][SecurityBundle][TwigBundle][Yaml] remove deprecated code (xabbuh)
* feature #23857 [HttpKernel] Remove convention based commands registration (chalasr)
* feature #23869 [Console] Made console command shortcuts case insensitive (thanosp)
* feature #23855 [DI] Allow dumping inline services in Yaml (nicolas-grekas)
* feature #23836 [FrameworkBundle] Catch Fatal errors in commands registration (chalasr)
* feature #23805 [HttpKernel] Deprecated commands auto-registration (GuilhemN)
* feature #23816 [Debug] Detect internal and deprecated methods (GuilhemN)
* feature #23812 [FrameworkBundle] Allow micro kernel to subscribe events easily (ogizanagi)
* feature #22187 [DependencyInjection] Support local binding (GuilhemN)
* feature #23741 [DI] Generate one file per service factory (nicolas-grekas)
* feature #23807 [Debug] Trigger a deprecation when using an internal class/trait/interface (GuilhemN)
* feature #22587 [Workflow] Add transition completed event (izzyp)
* feature #23624 [FrameworkBundle] Commands as a service (ro0NL)
* feature #21111 [Validator] add groups support to the Valid constraint (xabbuh)
* feature #20361 [Config] Enable cannotBeEmpty along with requiresAtLeastOneElement (ro0NL)
* feature #23790 [Yaml] remove legacy php/const and php/object tag support (xabbuh)
* feature #23754 [Lock] Remove Filesystem\LockHandler (jderusse)
* feature #23712 [DependencyInjection] Deprecate autowiring service auto-registration (GuilhemN)
* feature #23719 Autoconfigure instances of ArgumentValueResolverInterface (BPScott)
* feature #23706 [Webprofiler] Improve sql explain table display (mimol91)
* feature #23709 [VarDumper] Make dump() variadic (chalasr)
* feature #23724 [Lock] Deprecate Filesystem/LockHandler (jderusse)
* feature #23593 [Workflow] Adding workflow name to the announce event (Nyholm)
* feature #20496 [Form] Allow pass filter callback to delete_empty option. (Koc)
* feature #23451 [Cache] Add (filesystem|phpfiles) cache (adapter|simple) prune method and prune command (robfrawley)
* feature #23519 [TwigBundle] Commands as a service (ro0NL)
* feature #23591 [VarDumper] Add time zone caster (maidmaid)
* feature #23614 [VarDumper] Remove low PHP version and hhvm compat in interval caster (maidmaid)
* feature #22317 [Console] Make SymfonyQuestionHelper::ask optional by default (ro0NL)
* feature #23510 [Console] Add a factory command loader for standalone application with lazy-loading needs (ogizanagi)
* feature #23357 [VarDumper] Add interval caster (maidmaid)
* feature #23550 [DebugBundle] Added min_depth to Configuration (james-johnston-thumbtack)
* feature #23561 [DI] Optimize use of private and pre-defined services (nicolas-grekas)
* feature #23569 Remove last legacy codes (nicolas-grekas)
* feature #23570 [FrameworkBundle] Make RouterCacheWarmer implement ServiceSubscriberInterface (nicolas-grekas)
* feature #22783 [TwigBridge] remove deprecated features (xabbuh)
* feature #23437 [TwigBridge] deprecate TwigRenderer (Tobion)
* feature #22801 [DI] Removed deprecated setting private/pre-defined services (ro0NL)
* feature #23515 [VarDumper] Added setMinDepth to VarCloner (james-johnston-thumbtack)
* feature #23484 [DI] Remove remaining deprecated features (nicolas-grekas)
* feature #23404 [Serializer] AbstractObjectNormalizer: Allow to disable type enforcement (ogizanagi)
* feature #23380 [Process] Remove enhanced sigchild compatibility (maidmaid)
* feature #21086 [MonologBridge] Add TokenProcessor (maidmaid)
* feature #22576 [Validator] Allow to use a property path to get value to compare in comparison constraints (ogizanagi)
* feature #22689 [DoctrineBridge] Add support for doctrin/dbal v2.6 types (jvasseur)
* feature #22734 [Console] Add support for command lazy-loading (chalasr)
* feature #19034 [Security] make it possible to configure a custom access decision manager service (xabbuh)
* feature #23037 [TwigBundle] Added a RuntimeExtensionInterface to take advantage of autoconfigure (lyrixx)
* feature #22811 [DI] Remove deprecated case insensitive service ids (ro0NL)
* feature #22176 [DI] Allow imports in string format for YAML (ro0NL)
* feature #23295 [Security] Lazy load user providers (chalasr)
* feature #23440 [Routing] Add matched and default parameters to redirect responses (artursvonda, Tobion)
* feature #22804 [Debug] Removed ContextErrorException (mbabker)
* feature #22762 [Yaml] Support tagged scalars (GuilhemN)
* feature #22832 [Debug] Deprecate support for stacked errors (mbabker)
* feature #21469 [HttpFoundation] Find the original request protocol version (thewilkybarkid)
* feature #23431 [Validator] Add min/max amount of pixels to Image constraint (akeeman)
* feature #23223 Add support for microseconds in Stopwatch (javiereguiluz)
* feature #22341 [BrowserKit] Emulate back/forward browser navigation (e-moe)
* feature #22619 [FrameworkBundle][Translation] Move translation compiler pass (lepiaf)
* feature #22620 [FrameworkBundle][HttpKernel] Move httpkernel pass (lepiaf)
* feature #23402 [Ldap] Remove the RenameEntryInterface interface (maidmaid)
* feature #23337 [Component][Serializer][Normalizer] : Deal it with Has Method for the Normalizer/Denormalizer (jordscream)
* feature #23391 [Validator] Remove support of boolean value for the checkDNS option (maidmaid)
* feature #23376 [Process] Remove enhanced Windows compatibility (maidmaid)
* feature #22588 [VarDumper] Add filter in VarDumperTestTrait (maidmaid)
* feature #23288 [Yaml] deprecate the !str tag (xabbuh)
* feature #23039 [Validator] Support for parsing PHP constants in yaml loader (mimol91)
* feature #22431 [VarDumper] Add date caster (maidmaid)
* feature #23285 [Stopwatch] Add a reset method (jmgq)
* feature #23320 [WebServer] Allow * to bind all interfaces (as INADDR_ANY) (jpauli, fabpot)
* feature #23272 [FrameworkBundle] disable unusable fragment renderers (xabbuh)
* feature #23332 [Yaml] fix the displayed line number (fabpot, xabbuh)
* feature #23324 [Security] remove support for defining voters that don't implement VoterInterface. (hhamon)
* feature #23294 [Yaml][Lint] Add line numbers to JSON output. (WybrenKoelmans)
* feature #22836 [Process] remove deprecated features (xabbuh)
* feature #23286 [Yaml] remove deprecated unspecific tag behavior (xabbuh)
* feature #23026 [SecurityBundle] Add user impersonation info and exit action to the profiler (yceruto)
* feature #22863 [HttpFoundation] remove deprecated features (xabbuh)
* feature #22932 [HttpFoundation] Adds support for the immutable directive in the cache-control header (twoleds)
* feature #22554 [Profiler][Validator] Add a validator panel in profiler (ogizanagi)
* feature #22124 Shift responsibility for keeping Date header to ResponseHeaderBag (mpdude)
* feature #23122 Xml encoder optional type cast (ragboyjr)
* feature #23207 [FrameworkBundle] Allow .yaml file extension everywhere (ogizanagi)
* feature #23076 [Validator] Adds support to check specific DNS record type for URL (iisisrael)
* feature #22629 [Security] Trigger a deprecation when a voter is missing the VoterInterface (iltar)
* feature #22636 [Routing] Expose request in route conditions, if needed and possible (ro0NL)
* feature #22909 [Yaml] Deprecate using the non-specific tag (GuilhemN)
* feature #23184 [HttpFoundation] Remove obsolete ini settings for sessions (fabpot)
* feature #23042 Consistent error handling in remember me services (lstrojny)
* feature #22444 [Serializer] DateTimeNormalizer: allow to provide timezone (ogizanagi)
* feature #23143 [DI] Reference instead of inline for array-params (nicolas-grekas)
* feature #23154 [WebProfilerBundle] Sticky ajax window (ro0NL)
* feature #23161 [FrameworkBundle] Deprecate useless --no-prefix option (chalasr)
* feature #23169 [FrameworkBundle] Remove KernelTestCase deprecated code (ogizanagi)
* feature #23105 [SecurityBundle][Profiler] Give info about called security listeners in profiler (chalasr)
* feature #23148 [FrameworkBundle] drop hard dependency on the Stopwatch component (xabbuh)
* feature #23131 [FrameworkBundle] Remove dependency on Doctrine cache (fabpot)
* feature #23114 [SecurityBundle] Lazy load security listeners (chalasr)
* feature #23111 [Process] Deprecate ProcessBuilder (nicolas-grekas)
* feature #22675 [FrameworkBundle] KernelTestCase: deprecate not using KERNEL_CLASS (ogizanagi)
* feature #22917 [VarDumper] Cycle prev/next searching in HTML dumps (ro0NL)
* feature #23044 Automatically enable the routing annotation loader (GuilhemN)
* feature #22696 [PropertyInfo] Made ReflectionExtractor's prefix lists instance variables (neemzy)
* feature #23056 [WebProfilerBundle] Remove WebProfilerExtension::dumpValue() (ogizanagi)
* feature #23035 Deprecate passing a concrete service in optional cache warmers (romainneutron)
* feature #23036 Implement ServiceSubscriberInterface in optional cache warmers (romainneutron)
* feature #23046 [Form] Missing deprecated paths removal (ogizanagi)
* feature #23022 [Di] Remove closure-proxy arguments (nicolas-grekas)
* feature #22758 Remove HHVM support (fabpot)
* feature #22743 [Serializer] Remove support for deprecated signatures (dunglas)
* feature #22907 [Serializer] remove remaining deprecated features (xabbuh)
* feature #22886 [HttpKernel] remove deprecated features (xabbuh)
* feature #22906 [Console] remove remaining deprecated features (xabbuh)
* feature #22879 [Translation] remove deprecated features (xabbuh)
* feature #22880 [Routing] remove deprecated features (xabbuh)
* feature #22903 [DI] Deprecate XML services without ID (ro0NL)
* feature #22770 [Yaml] remove deprecated features (xabbuh)
* feature #22785 [ProxyManagerBridge] remove deprecated features (xabbuh)
* feature #22800 [FrameworkBundle] Remove deprecated code (ogizanagi)
* feature #22597 [Lock] Re-add the Lock component in 3.4 (jderusse)
* feature #22860 [Form] remove deprecated features (xabbuh)
* feature #22803 [DI] Deprecate Container::initialized() for privates (ro0NL)
* feature #22773 [DependencyInjection] remove deprecated autowiring_types feature (hhamon)
* feature #22809 [DI] Remove deprecated generating a dumped container without populating the method map (ro0NL)
* feature #22764 [DI] Remove deprecated dumping an uncompiled container (ro0NL)
* feature #22820 Remove PHP < 7.1.3 code (ogizanagi)
* feature #22763 [DI] Remove deprecated isFrozen() (ro0NL)
* feature #22837 [VarDumper] remove deprecated features (xabbuh)
* feature #22777 [Console] Remove deprecated console.exception event (mbabker)
* feature #22792 [PhpUnitBridge] remove deprecated features (xabbuh)
* feature #22821 [Security] remove deprecated features (xabbuh)
* feature #22750 [DependencyInjection] remove deprecated code in YamlFileLoader class (hhamon)
* feature #22828 [Finder] Deprecate FilterIterator (ogizanagi)
* feature #22791 [MonologBridge] remove deprecated features (xabbuh)
* feature #22740 [SecurityBundle][Security][Finder] Remove deprecated code paths (ogizanagi)
* feature #22823 [PropertyAccess] remove deprecated features (xabbuh)
* feature #22826 [Validator] improve strict option value deprecation (xabbuh)
* feature #22799 [Console] Remove deprecated features (chalasr)
* feature #22786 [ClassLoader][HttpKernel] Remove ClassLoader component & Kernel::loadClassCache (ogizanagi, xabbuh)
* feature #22795 [Validator] remove deprecated features (xabbuh)
* feature #22784 [DoctrineBridge] remove deprecated features (xabbuh)
* feature #22749 Remove deprecated container injections and compiler passes (chalasr)
* feature #22796 [EventDispatcher] remove deprecated features (xabbuh)
* feature #22797 [Ldap] remove deprecated features (xabbuh)
* feature #22794 [ExpressionLanguage] remove deprecated features (xabbuh)
* feature #22779 [BC Break] Removed BC layers for ControllerResolver::getArguments() (iltar)
* feature #22782 [Debug][VarDumper] Remove the symfony_debug C extension (nicolas-grekas)
* feature #22771 [Workflow] Removed deprecated features (lyrixx)
* feature #22741 [Serializer] Remove deprecated DoctrineCache support (dunglas)
* feature #22733 Bump minimum version to PHP 7.1 for Symfony 4 (fabpot, dunglas, nicolas-grekas)

View File

@ -0,0 +1,586 @@
CHANGELOG for 4.1.x
===================
This changelog references the relevant changes (bug and security fixes) done
in 4.1 minor versions.
To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash
To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v4.1.0...v4.1.1
* 4.1.10 (2019-01-06)
* bug #29494 [HttpFoundation] Fix request uri when it starts with double slashes (alquerci)
* bug #29697 [DI] Fixed wrong factory method in exception (Wojciech Gorczyca)
* bug #29679 [HttpKernel] Correctly Render Signed URIs Containing Fragments (zanbaldwin)
* bug #29754 Ensure final input of CommandTester works with default (Firehed)
* bug #29695 [Form] Do not ignore the choice groups for caching (vudaltsov)
* bug #29738 [Intl] handle null date and time types (xabbuh)
* bug #29708 [FrameworkBundle] access the container getting it from the kernel (xabbuh)
* bug #29704 [FrameworkBundle] improve errors in tests missing the BrowserKit component (xabbuh)
* bug #29617 [Console] Add specific replacement for help text in single command applications (codedmonkey)
* bug #29714 [Event Dispatcher] fixed 29703: TraceableEventDispatcher reset() callStack to null (mlievertz)
* bug #29597 [DI] fix reporting bindings on overriden services as unused (nicolas-grekas)
* bug #29639 [Yaml] detect circular references (xabbuh)
* bug #29626 [Routing] fix trailing slash redirections involving a trailing var (nicolas-grekas)
* bug #29411 [EventDispatcher] Revers event tracing order (ro0NL)
* bug #29533 Fixed public directory when configured in composer.json (alexander-schranz)
* bug #29619 [Console] OutputFormatter: move strtolower to createStyleFromString (ogizanagi)
* bug #29621 [Security] Prefer clone() over unserialize(serialize()) for user refreshment (chalasr)
* bug #29542 [Routing] fix dumping same-path routes with placeholders (nicolas-grekas)
* bug #29587 [Debug] ignore underscore vs backslash namespaces in DebugClassLoader (nicolas-grekas)
* bug #29584 [FrameworkBundle] fix describing routes with no controllers (nicolas-grekas)
* bug #29582 [DI] move RegisterServiceSubscribersPass before DecoratorServicePass (kbond)
* bug #29527 [TwigBridge][Form] Prevent multiple rendering of form collection prototypes (Shoplifter)
* bug #29571 [Yaml] ensures that the mb_internal_encoding is reset to its initial value (Jörn Lang)
* bug #29513 [Hackday][Serializer] Deserialization ignores argument type hint from phpdoc for array in constructor argument (karser)
* bug #29323 [Security] defer log message in guard authenticator (eschultz-magix)
* bug #29531 [Validator] Added IBAN format for Vatican City State (raulfraile)
* bug #29501 [Form] filter out invalid language values (xabbuh)
* bug #29307 [Form] Filter arrays out of scalar form types (nicolas-grekas)
* bug #29500 [Form] filter out invalid Intl values (xabbuh)
* bug #29499 [Validator] Fixed grouped composite constraints (HeahDude)
* 4.1.9 (2018-12-06)
* security #cve-2018-19790 [Security\Http] detect bad redirect targets using backslashes (xabbuh)
* security #cve-2018-19789 [Form] Filter file uploads out of regular form types (nicolas-grekas)
* bug #29436 [Cache] Fixed Memcached adapter doClear()to call flush() (raitocz)
* bug #29441 [Routing] ignore trailing slash for non-GET requests (nicolas-grekas)
* bug #29444 [Workflow] Fixed BC break for Workflow metadata (lyrixx)
* bug #29432 [DI] dont inline when lazy edges are found (nicolas-grekas)
* bug #29413 [Serializer] fixed DateTimeNormalizer to maintain microseconds when a different timezone required (rvitaliy)
* bug #29424 [Routing] fix taking verb into account when redirecting (nicolas-grekas)
* bug #29414 [DI] Fix dumping expressions accessing single-use private services (chalasr)
* bug #29375 [Validator] Allow `ConstraintViolation::__toString()` to expose codes that are not null or emtpy strings (phansys)
* bug #29376 [EventDispatcher] Fix eventListener wrapper loop in TraceableEventDispatcher (jderusse)
* bug #29386 undeprecate the single-colon notation for controllers (fbourigault)
* bug #29393 [DI] fix edge case in InlineServiceDefinitionsPass (nicolas-grekas)
* bug #29380 [Routing] fix greediness of trailing slash (nicolas-grekas)
* bug #29343 [Form] Handle all case variants of "nan" when parsing a number (mwhudson, xabbuh)
* bug #29373 [Routing] fix trailing slash redirection (nicolas-grekas)
* bug #29355 [PropertyAccess] calculate cache keys for property setters depending on the value (xabbuh)
* bug #29369 [DI] fix combinatorial explosion when analyzing the service graph (nicolas-grekas)
* bug #29349 [Debug] workaround opcache bug mutating "$this" !?! (nicolas-grekas)
* 4.1.8 (2018-11-26)
* bug #29318 [Console] Move back root exception to stack trace in verbose mode (chalasr)
* bug #29332 [PropertyAccess] make cache keys encoding bijective (nicolas-grekas)
* bug #29298 [Routing] fix trailing slash redirection when using RedirectableUrlMatcher (nicolas-grekas)
* bug #29297 [Routing] fix trailing slash redirection when using RedirectableUrlMatcher (nicolas-grekas)
* bug #29313 [PropertyAccessor] fix encoding of cache keys (nicolas-grekas)
* bug #28917 [DoctrineBridge] catch errors while converting to db values in data collector (alekitto)
* bug #29317 [WebProfiler] Detect non-file paths in file viewer (ro0NL)
* bug #29305 [EventDispatcher] Unwrap wrapped listeners internally (ro0NL)
* bug #27314 [DoctrineBridge] fix case sensitivity issue in RememberMe\DoctrineTokenProvider (PF4Public)
* bug #29310 [MonologBridge] Return empty list for unknown requests (ro0NL)
* bug #29308 [Translation] Use XLIFF source rather than resname when there's no target (thewilkybarkid)
* bug #26244 [BrowserKit] fixed BC Break for HTTP_HOST header (brizzz)
* bug #28147 [DomCrawler] exclude fields inside "template" tags (Gorjunov)
* bug #29222 [Dotenv] properly parse backslashes in unquoted env vars (xabbuh)
* bug #29256 [HttpFoundation] Fixed absolute Request URI with default port (thomasbisignani)
* bug #29274 [Routing] Remove duplicate schemes and methods for invokable controllers (claudusd)
* bug #29271 [HttpFoundation] Fix trailing space for mime-type with parameters (Sascha Dens)
* bug #29243 [Cache] fix optimizing Psr6Cache for AdapterInterface pools (nicolas-grekas)
* bug #29247 [DI] fix taking lazy services into account when dumping the container (nicolas-grekas)
* bug #29249 [Form] Fixed empty data for compound date interval (HeahDude)
* bug #29265 [Bridge/PhpUnit] Use composer to download phpunit (nicolas-grekas)
* bug #28769 [FrameworkBundle] deal with explicitly enabled workflow nodes (xabbuh)
* bug #29223 [Validator] Added the missing constraints instance checks (thomasbisignani)
* bug #28966 [PropertyAccessor] Fix unable to write to singular property using setter while plural adder/remover exist (karser)
* bug #29182 [Form] Fixed empty data for compound date types (HeahDude)
* bug #29191 [Routing] generate(null) should throw an exception (nicolas-grekas)
* bug #29185 [Form] Fixed keeping hash of equal \DateTimeInterface on submit (HeahDude)
* bug #29141 [Workflow] Fixed bug of buildTransitionBlockerList when many transition are enabled (Tetragramat, lyrixx)
* bug #29137 [Workflow][FrameworkBundle] fixed guard event names for transitions (destillat, lyrixx)
* bug #28731 [Form] invalidate forms on transformation failures (xabbuh)
* bug #29152 [Config] Unset key during normalization (ro0NL)
* bug #29165 [DI] align IniFileLoader to PHP bugfix #76965 (nicolas-grekas)
* bug #29115 Change button_widget class to btn-primary (neFAST)
* bug #29131 [Dotenv] dont use getenv() to read SYMFONY_DOTENV_VARS (nicolas-grekas)
* bug #29057 [HttpFoundation] replace any preexisting Content-Type headers (nicolas-grekas)
* bug #29076 [Serializer] Allow null values when denormalizing with constructor missing data (danut007ro)
* bug #29104 [DI] fix dumping inlined services (nicolas-grekas)
* bug #29054 [VarDumper] fix dump of closures created from callables (nicolas-grekas)
* bug #29102 [DI] fix GraphvizDumper ignoring inline definitions (nicolas-grekas)
* bug #29107 [DI] dont track classes/interfaces used to compute autowiring error messages (nicolas-grekas)
* 4.1.7 (2018-11-03)
* bug #28820 [DependencyInjection] Fix tags on multiple decorated service (Soner Sayakci)
* bug #29020 Fix ini_get() for boolean values (deguif)
* bug #28955 [Messenger] send using the routing_key for AMQP transport (nicolas-grekas)
* bug #28960 also clean away the NO_AUTO_CACHE_CONTROL_HEADER if we have no session (dbu)
* feature #28893 [TwigBundle] Fix usage of TwigBundle without FrameworkBundle (tgalopin)
* bug #28889 [Serializer] Reduce class discriminator overhead (fbourigault)
* bug #28861 [DependencyInjection] Skip empty proxy code (olvlvl)
* bug #28801 Convert InsufficientAuthenticationException to HttpException with 401 status code (vincentchalamon)
* bug #28840 add missing double-quotes to extra_fields output message (danielkay)
* bug #28838 [DI] Default undefined env to empty string during compile (ro0NL)
* bug #28863 [Process] Allow to pass non-string arguments to Process (vudaltsov)
* bug #28712 [Form] reverse transform RFC 3339 formatted dates (xabbuh)
* bug #28813 Fix for race condition in console output stream write (rudolfratusinski)
* bug #27772 [Console] Fixes multiselect choice question defaults in non-interactive mode (veewee)
* bug #28835 [FrameworkBundle] Setting missing default paths under BC layer (yceruto)
* bug #28760 [DI] fix dumping inline services again (nicolas-grekas)
* bug #28689 [Process] fix locking of pipe files on Windows (nicolas-grekas)
* bug #28704 [Form] fix multi-digit seconds fraction handling (xabbuh)
* bug #28793 [SecurityBundle] do not override custom access decision configs (xabbuh)
* bug #28783 [FrameworkBundle] add missing cache prefix seed attribute to XSD (xabbuh)
* bug #28072 [Security] Do not deauthenticate user when the first refreshed user has changed (gpekz)
* bug #28735 [FWBundle] Automatically enable PropertyInfo when using Flex (dunglas)
* bug #28751 [FrameworkBundle] Register messenger before the profiler (sroze)
* 4.1.6 (2018-10-03)
* bug #28604 [Finder] fixed root directory access for ftp/sftp wrapper (DerDu)
* bug #28688 [FWBundle] Throw if PropertyInfo is enabled, but the component isn't installed (dunglas)
* bug #28638 [Console] Fix clearing sections containing questions (chalasr)
* bug #28690 [FrameworkBundle] dont suggest hidden services in debug:container and debug:autow commands (nicolas-grekas)
* bug #28648 [PHPUnitBridge] Fix ClockMock microtime() format (acasademont)
* bug #28678 [DI] fix dumping setters before their inlined instances (nicolas-grekas)
* bug #28672 [DI] fix error in dumped container (nicolas-grekas)
* bug #28664 [Console] Don't return early as this bypasses the auto exit feature (duncan3dc)
* 4.1.5 (2018-09-30)
* bug #28636 [HttpFoundation] X-Accel-Mapping does not use HTTP key=value syntax (c960657)
* bug #28376 [TwigBundle] Fixed caching of templates in src/Resources/<BundleName>/views on cache warmup (yceruto)
* bug #28565 [HttpFoundation][Security] forward locale and format to subrequests (nicolas-grekas)
* bug #28561 [Cache] prevent getting older entries when the version key is evicted (nicolas-grekas)
* bug #28562 [HttpFoundation] fix hidding warnings from session handlers (nicolas-grekas)
* bug #28545 [Console] Send the right exit code to console.terminate listeners (mpdude)
* bug #28553 [Debug] Fix false-positive "MicroKernelTrait::loadRoutes()" method is considered internal" (nicolas-grekas)
* bug #28466 [Form] fail reverse transforming invalid RFC 3339 dates (xabbuh)
* bug #28540 [Intl] parse numbers terminated with decimal separator (xabbuh)
* bug #28548 [Console] Fixed boxed table style with colspan (ro0NL)
* bug #28433 [HttpFoundation] Allow reuse of Session between requests if ID did not change (tgalopin)
* bug #28508 [Form] forward false label option to nested types (xabbuh)
* bug #28471 [MonologBridge] Re-add option option to ignore empty context and extra data (mpdude)
* bug #28464 [Form] forward the invalid_message option in date types (xabbuh)
* bug #28524 [PhpUnitBridge] fix disabling DeprecationErrorHandler using phpunit.xml file (soerenbernstein)
* bug #28512 [DI] fix infinite loop involving self-references in decorated services (nicolas-grekas)
* bug #28507 [DI] fix dumping lazy services (nicolas-grekas)
* bug #28469 [Form][TwigBridge] fix not displaying labels when value is false (xabbuh)
* bug #28495 [PhpUnitBridge] Implement startTest rather than startTestSuite (greg0ire)
* bug #28480 [DI] Detect circular references with ChildDefinition parent (Seb33300)
* bug #28497 [VarDumper] Fix global dump function return value for PHP7 (patrickcarlohickman)
* bug #28499 [Ldap] Use shut up operator on connection errors at ldap_start_tls (Andras Debreczeni)
* bug #28372 [Form] Fix DateTimeType html5 input format (franzwilding, mcfedr)
* bug #28396 [Intl] Blacklist Eurozone and United Nations in Region Data Generator (gregurco)
* bug #28418 [FrameworkBundle] Register the messenger data collector only when the profiler is enabled (pierredup)
* bug #28393 [Console] fixed corrupt error output for unknown multibyte short option (downace)
* bug #28411 [Debug] fix detecting overriden final/internal methods implemented using traits (nicolas-grekas)
* bug #28404 [Controller][ServiceValueResolver] Making method access case insensitive (nicoweb)
* bug #28401 [Console] Fix SymfonyQuestionHelper::askQuestion() with choice value as default (chalasr)
* bug #28388 [DI] configure inlined services before injecting them when dumping the container (nicolas-grekas)
* bug #28377 fix fopen flags (SpacePossum)
* bug #27764 [TwigBundle] Fixed caching of templates in default path on cache warmup (yceruto)
* bug #28366 [DI] Fix dumping some complex service graphs (nicolas-grekas)
* bug #27970 [FileValidator] Format file size in validation message according to binaryFormat option (jfredon)
* bug #28029 [TwigBundle] remove cache warmers when Twig cache is disabled (xabbuh)
* bug #28322 [Workflow] Make sure we do not run the next transition on an updated state (Nyholm)
* bug #28344 [HttpKernel][FrameworkBundle] Fix escaping of serialized payloads passed to test clients (nicolas-grekas)
* bug #28183 [WebProfilerBundle] fix wrong url when base path is the index (ismail1432)
* bug #28334 [FWB][Messenger] Revert "Move commands-specifics to a compiler pass in FWB" (sroze)
* bug #28328 [Messenger][FrameworkBundle] Move commands-specifics to a compiler pass in FWB (sroze)
* 4.1.4 (2018-08-28)
* bug #28278 [HttpFoundation] Fix unprepared BinaryFileResponse sends empty file (wackymole)
* bug #28284 [PhpUnitBridge] keep compat with composer 1.0 (nicolas-grekas)
* bug #28251 [HttpFoundation] Allow RedisCluster class for RedisSessionHandler (michaelperrin)
* bug #28241 [HttpKernel] fix forwarding trusted headers as server parameters (nicolas-grekas)
* bug #28220 [PropertyAccess] fix type error handling when writing values (xabbuh)
* bug #28249 [Cache] enable Memcached::OPT_TCP_NODELAY to fix perf of misses (nicolas-grekas)
* bug #28252 [DoctrineBridge] support __toString as documented for UniqueEntityValidator (dmaicher)
* bug #28216 [FrameworkBundle] `message_bus` alias public (sroze)
* bug #28113 [Form] Add help texts for checkboxes in horizontal bootstrap 4 forms (apfelbox)
* bug #28100 [Security] Call AccessListener after LogoutListener (chalasr)
* bug #28174 Remove the HTML5 validation from the profiler URL search form (Soullivaneuh)
* bug #28159 [DI] Fix autowire inner service (hason)
* bug #28060 [DI] Fix false-positive circular ref leading to wrong exceptions or infinite loops at runtime (nicolas-grekas)
* bug #28144 [HttpFoundation] fix false-positive ConflictingHeadersException (nicolas-grekas)
* bug #28152 [Translation] fix perf of lint:xliff command (nicolas-grekas)
* bug #28115 [Form] Remove extra .form-group wrapper around file widget in bootstrap 4 (MrMitch)
* bug #28120 [Routing] Fixed scheme redirecting for root path (twoleds)
* bug #28112 Fix CSS property typo (AhmedAbdulrahman)
* bug #28012 [PropertyInfo] Allow nested collections (jderusse)
* bug #28055 [PropertyInfo] Allow nested collections (jderusse)
* bug #28083 Remove the Expires header when calling Response::expire() (javiereguiluz)
* 4.1.3 (2018-08-01)
* security #cve-2018-14774 [HttpKernel] fix trusted headers management in HttpCache and InlineFragmentRenderer (nicolas-grekas)
* security #cve-2018-14773 [HttpFoundation] Remove support for legacy and risky HTTP headers (nicolas-grekas)
* bug #28003 [HttpKernel] Fixes invalid REMOTE_ADDR in inline subrequest when configuring trusted proxy with subnet (netiul)
* bug #28007 [FrameworkBundle] fixed guard event names for transitions (destillat)
* bug #28045 [HttpFoundation] Fix Cookie::isCleared (ro0NL)
* bug #28080 [HttpFoundation] fixed using _method parameter with invalid type (Phobetor)
* bug #28059 [Messenger] Fix error message on undefined message class for non-subscriber handler (chalasr)
* bug #28052 [HttpKernel] Fix merging bindings for controllers' locators (nicolas-grekas)
* bug #28014 [Messenger] Fix chaining senders with their aliases (sroze)
* 4.1.2 (2018-07-23)
* bug #28005 [HttpKernel] Fixed templateExists on parse error of the template name (yceruto)
* bug #28013 [Messenger] Add missing typehint on chain sender (sroze)
* bug #27997 Serbo-Croatian has Serbian plural rule (kylekatarnls)
* bug #26193 Fix false-positive deprecation notices for TranslationLoader and WriteCheckSessionHandler (iquito)
* bug #27827 [Serializer] Supports nested abstract items (sroze)
* bug #27958 [Form] Remaining changes for bootstrap 4 file fields (apfelbox)
* bug #27919 [Form] Improve rendering of `file` field in bootstrap 4 (apfelbox)
* bug #27941 [WebProfilerBundle] Fixed icon alignment issue using Bootstrap 4.1.2 (jmsche)
* bug #27937 [HttpFoundation] reset callback on StreamedResponse when setNotModified() is called (rubencm)
* bug #27927 [HttpFoundation] Suppress side effects in 'get' and 'has' methods of NamespacedAttributeBag (webnet-fr)
* bug #27913 [EventDispatcher] Clear orphaned events on reset (acasademont)
* bug #27923 [Form/Profiler] Massively reducing memory footprint of form profiling pages... (VincentChalnot)
* bug #27918 [Console] correctly return parameter's default value on "--" (seschwar)
* bug #27826 [Serializer] Fix serialization of items with groups across entities and discrimination map (sroze)
* bug #27904 [Filesystem] fix lock file permissions (fritzmg)
* bug #27903 [Lock] fix lock file permissions (fritzmg)
* bug #27889 [Form] Replace .initialism with .text-uppercase. (vudaltsov)
* bug #27902 Fix the detection of the Process new argument (stof)
* bug #27885 [HttpFoundation] don't encode cookie name for BC (nicolas-grekas)
* bug #27782 [DI] Fix dumping ignore-on-uninitialized references to synthetic services (nicolas-grekas)
* bug #27435 [OptionResolver] resolve arrays (Doctrs)
* bug #27728 [TwigBridge] Fix missing path and separators in loader paths list on debug:twig output (yceruto)
* bug #27837 [PropertyInfo] Fix dock block lookup fallback loop (DerManoMann)
* bug #27848 [Workflow] Fixed BC break (lyrixx)
* bug #27758 [WebProfilerBundle] Prevent toolbar links color override by css (alcalyn)
* bug #27847 [Security] Fix accepting null as $uidKey in LdapUserProvider (louhde)
* bug #27820 [Messenger] Fix a bug when having more than one named handler per message subscriber (sroze)
* bug #27834 [DI] Don't show internal service id on binding errors (nicolas-grekas)
* bug #27831 Check for Hyper terminal on all operating systems. (azjezz)
* bug #27794 Add color support for Hyper terminal . (azjezz)
* bug #27809 [HttpFoundation] Fix tests: new message for status 425 (dunglas)
* bug #27618 [PropertyInfo] added handling of nullable types in PhpDoc (oxan)
* bug #27659 [HttpKernel] Make AbstractTestSessionListener compatible with CookieClearingLogoutHandler (thewilkybarkid)
* bug #27752 [Cache] provider does not respect option maxIdLength with versioning enabled (Constantine Shtompel)
* bug #27773 [Serializer] Class discriminator and serialization groups (sroze)
* bug #27710 [DependencyInjection] fix handling of empty DI extension configs (xabbuh)
* bug #27776 [ProxyManagerBridge] Fix support of private services (bis) (nicolas-grekas)
* bug #27714 [HttpFoundation] fix session tracking counter (nicolas-grekas, dmaicher)
* bug #27727 [Routing] Disallow object usage inside Route (paxal)
* bug #27736 [Routing] fix too much greediness in host-matching regex (nicolas-grekas)
* bug #27747 [HttpFoundation] fix registration of session proxies (nicolas-grekas)
* bug #27754 [HttpFoundation] missing namespace for RedisProxy (Bonfante)
* bug #27722 Redesign the Debug error page in prod (javiereguiluz)
* bug #27716 [DI] fix dumping deprecated service in yaml (nicolas-grekas)
* 4.1.1 (2018-06-25)
* bug #27626 [TwigBundle][DX] Only add the Twig WebLinkExtension if the WebLink component is enabled (thewilkybarkid)
* bug #27702 [TwigBundle] bump lowest deps to fix issue with "double-colon" controller service refs (nicolas-grekas)
* bug #27701 [SecurityBundle] Dont throw if "security.http_utils" is not found (nicolas-grekas)
* bug #27690 [DI] Resolve env placeholder in logs (ro0NL)
* bug #27687 [HttpKernel] fix argument's error messages in ServiceValueResolver (nicolas-grekas)
* bug #27614 [VarDumper] Fix dumping by splitting Server/Connection out of Dumper/ServerDumper (nicolas-grekas)
* bug #27681 [DI] Avoid leaking unused env placeholders (ro0NL)
* bug #26534 allow_extra_attributes does not throw an exception as documented (deviantintegral)
* bug #27664 [FrameworkBundle] Ignore keepQueryParams attribute when generating route redirect (vudaltsov)
* bug #27668 [Lock] use 'r+' for fopen (fixes issue on Solaris) (fritzmg)
* bug #27669 [Filesystem] fix file lock on SunOS (fritzmg)
* bug #27662 [HttpKernel] fix handling of nested Error instances (xabbuh)
* bug #27651 [Messenger] Fixed MessengerPass::guessHandledClasses return type (massimilianobraglia)
* bug #26845 [Config] Fixing GlobResource when inside phar archive (vworldat)
* bug #27382 [Form] Fix error when rendering a DateIntervalType form with exactly 0 weeks (krixon)
* bug #27309 Fix surrogate not using original request (Toflar)
* bug #27467 [HttpKernel] fix session tracking in surrogate master requests (nicolas-grekas)
* bug #27632 [HttpFoundation] Ensure RedisSessionHandler::updateTimestamp returns a boolean (MatTheCat)
* bug #27630 [Validator][Form] Remove BOM in some xlf files (gautierderuette)
* bug #27596 [Framework][Workflow] Added support for interfaces (vudaltsov)
* bug #27593 [ProxyManagerBridge] Fixed support of private services (nicolas-grekas)
* bug #27591 [VarDumper] Fix dumping ArrayObject and ArrayIterator instances (nicolas-grekas)
* bug #27528 [FrameworkBundle] give access to non-shared services when using test.service_container (nicolas-grekas)
* bug #27584 Avoid calling eval when there is no script embedded in the toolbar (stof)
* bug #27581 Fix bad method call with guard authentication + session migration (weaverryan)
* bug #27576 [Cache] Fix expiry comparisons in array-based pools (nicolas-grekas)
* bug #27566 [FrameworkBundle] fix for allowing single colon controller notation (dmaicher)
* bug #27556 Avoiding session migration for stateless firewall UsernamePasswordJsonAuthenticationListener (weaverryan)
* bug #27452 Avoid migration on stateless firewalls (weaverryan)
* bug #27568 [DI] Deduplicate generated proxy classes (nicolas-grekas)
* bug #27511 [Routing] fix matching host patterns, utf8 prefixes and non-capturing groups (nicolas-grekas)
* bug #27326 [Serializer] deserialize from xml: Fix a collection that contains the only one element (webnet-fr)
* bug #27562 [HttpKernel] Log/Collect exceptions at prio 0 (ro0NL)
* bug #27567 [PhpUnitBridge] Fix error on some Windows OS (Nsbx)
* bug #27357 [Lock] Remove released semaphore (jderusse)
* bug #27416 TagAwareAdapter over non-binary memcached connections corrupts memcache (Aleksey Prilipko)
* bug #27514 [Debug] Pass previous exception to FatalErrorException (pmontoya)
* bug #27516 Revert "bug #26138 [HttpKernel] Catch HttpExceptions when templating is not installed (cilefen)" (nicolas-grekas)
* bug #27501 [FrameworkBundle] Fix test-container on kernel reboot, revert to returning the real container from Client::getContainer() (nicolas-grekas)
* bug #27472 [DI] Ignore missing tree root nodes on validate (ro0NL)
* bug #27458 [WebProfilerBundle] fixed getSession when no session has been set deprecation warnings (GregOriol)
* bug #27318 [Cache] memcache connect should not add duplicate entries on sequential calls (Aleksey Prilipko)
* bug #27498 [Routing] Don't reorder past variable-length placeholders (nanocom, nicolas-grekas)
* bug #27496 [DebugBundle] DebugBundle::registerCommands should be noop (ogizanagi)
* bug #27485 [BrowserKit] Fix a BC break in Client affecting Panthère (dunglas)
* bug #27470 [DI] Remove default env type check on validate (ro0NL)
* bug #27454 [FrameworkBundle][TwigBridge] Fix BC break from strong dependency on CSRF token storage (tgalopin)
* bug #27389 [Serializer] Fix serializer tries to denormalize null values on nullable properties (ogizanagi)
* bug #27272 [FrameworkBundle] Change priority of AddConsoleCommandPass to TYPE_BEFORE_REMOVING (upyx)
* bug #27396 [HttpKernel] fix registering IDE links (nicolas-grekas)
* bug #26973 [HttpKernel] Set first trusted proxy as REMOTE_ADDR in InlineFragmentRenderer. (kmadejski)
* bug #27303 [Process] Consider "executable" suffixes first on Windows (sanmai)
* bug #27297 Triggering RememberMe's loginFail() when token cannot be created (weaverryan)
* 4.1.0 (2018-05-30)
* bug #27420 Revert "feature #26702 Mark ExceptionInterfaces throwable (ostrolucky)" (nicolas-grekas)
* bug #27415 Insert correct parameter_bag service in AbstractController (curry684)
* 4.1.0-BETA3 (2018-05-26)
* bug #27388 [Routing] Account for greediness when merging route patterns (nicolas-grekas)
* bug #27344 [HttpKernel] reset kernel start time on reboot (kiler129)
* bug #27365 [Serializer] Check the value of enable_max_depth if defined (dunglas)
* bug #27358 [PhpUnitBridge] silence some stderr outputs (ostrolucky)
* bug #27366 [DI] never inline lazy services (nicolas-grekas)
* bug #27352 Remove reference to the test container after kernel shutdown (stof)
* bug #27350 [HttpKernel] fix deprecation in AbstractTestSessionListener (alekitto)
* bug #27367 [FrameworkBundle] cleanup generated test container (nicolas-grekas)
* bug #27379 [FrameworkBundle] Fix using test.service_container when Client is rebooted (nicolas-grekas)
* bug #27364 [DI] Fix bad exception on uninitialized references to non-shared services (nicolas-grekas)
* bug #27359 [HttpFoundation] Fix perf issue during MimeTypeGuesser intialization (nicolas-grekas)
* security #cve-2018-11408 [SecurityBundle] Fail if security.http_utils cannot be configured
* security #cve-2018-11406 clear CSRF tokens when the user is logged out
* security #cve-2018-11385 migrating session for UsernamePasswordJsonAuthenticationListener
* security #cve-2018-11385 migrating session for UsernamePasswordJsonAuthenticationListener
* security #cve-2018-11385 Adding session authentication strategy to Guard to avoid session fixation
* security #cve-2018-11385 Adding session strategy to ALL listeners to avoid *any* possible fixation
* security #cve-2018-11386 [HttpFoundation] Break infinite loop in PdoSessionHandler when MySQL is in loose mode
* bug #27341 [WebProfilerBundle] Fixed validator/dump trace CSS (yceruto)
* bug #27337 [FrameworkBundle] fix typo in CacheClearCommand (emilielorenzo)
* bug #27292 [Serializer] Fix and improve constraintViolationListNormalizer's RFC7807 compliance (dunglas)
* 4.1.0-BETA2 (2018-05-21)
* bug #27312 Supress deprecation notices thrown when getting private servies from container in tests (arderyp)
* feature #27275 [Messenger] Allow to scope handlers per bus (ogizanagi, sroze)
* bug #27264 [Validator] Use strict type in URL validator (mimol91)
* bug #27267 [DependencyInjection] resolve array env vars (jamesthomasonjr)
* bug #26781 [Form] Fix precision of MoneyToLocalizedStringTransformer's divisions on transform() (syastrebov)
* bug #27270 [Routing] Fix adding name prefix to canonical route names (ismail1432)
* bug #27286 [Translation] Add Occitan plural rule (kylekatarnls)
* bug #27271 [DI] Allow defining bindings on ChildDefinition (nicolas-grekas)
* bug #27246 Disallow invalid characters in session.name (ostrolucky)
* feature #27230 [Messenger] Select alternatives on missing receiver arg or typo (yceruto)
* bug #27287 [PropertyInfo] fix resolving parent|self type hints (nicolas-grekas)
* bug #27281 [HttpKernel] Fix dealing with self/parent in ArgumentMetadataFactory (fabpot)
* bug #24805 [Security] Fix logout (MatTheCat)
* bug #27265 [DI] Shared services should not be inlined in non-shared ones (nicolas-grekas)
* bug #27141 [Process] Suppress warnings when open_basedir is non-empty (cbj4074)
* bug #27250 [Session] limiting :key for GET_LOCK to 64 chars (oleg-andreyev)
* feature #27128 [Messenger] Middleware factories support in config (ogizanagi)
* bug #27214 [HttpKernel] Fix services are no longer injected into __invoke controllers method (ogizanagi)
* bug #27237 [Debug] Fix populating error_get_last() for handled silent errors (nicolas-grekas)
* bug #27232 [Cache][Lock] Fix usages of error_get_last() (nicolas-grekas)
* bug #27236 [Filesystem] Fix usages of error_get_last() (nicolas-grekas)
* feature #27202 [Messenger] Improve the profiler panel (ogizanagi)
* bug #27191 [DI] Display previous error messages when throwing unused bindings (nicolas-grekas)
* bug #27231 [FrameworkBundle] Fix cache:clear on vagrant (nicolas-grekas)
* bug #27222 [WebProfilerBundle][Cache] Fix misses calculation when calling getItems (fsevestre)
* bug #27227 [HttpKernel] Handle NoConfigurationException "onKernelException()" (nicolas-grekas)
* feature #27034 [Messenger][DX] Uses custom method names for handlers (sroze)
* bug #27228 [Messenger] Remove autoconfiguration for Sender/ReceiverInterface (kbond)
* bug #27229 [Messenger] Rename tag attribute "name" by "alias" (yceruto)
* bug #27224 [Messenger] Make sure default receiver name is set before command configuration (yceruto)
* feature #27225 [Messenger] Autoconfiguring TransportFactoryInterface classes (yceruto)
* bug #27220 [Messenger] Fix new AMQP Transport test with Envelope & fix contract (ogizanagi)
* bug #27184 [Messenger] Fix return senders based on the message parents/interfaces (yceruto)
* feature #27182 [Messenger] Re-introduce wrapped message configuration (with fix) (sroze, ogizanagi)
* bug #27209 [Workflow] add is deprecated since Symfony 4.1. Use addWorkflow() instead (xkobal)
* feature #26803 [Messenger] Add debug:messenger CLI command (ro0NL, sroze)
* bug #27189 [Profiler] Fix dump makes toolbar disappear (ogizanagi)
* bug #27199 [Messenger] Fix default bus name (ogizanagi)
* bug #27198 [Messenger] Fix the transport factory after moving it (sroze)
* bug #27197 [Messenger] Fix AMQP Transport factory & TransportFactoryInterface (ogizanagi)
* bug #27196 [Messenger] Fix AMQP Transport (yceruto)
* 4.1.0-BETA1 (2018-05-07)
* feature #26945 [Messenger] Support configuring messages when dispatching (ogizanagi)
* feature #27168 [HttpKernel] Add Kernel::getAnnotatedClassesToCompile() (nicolas-grekas)
* feature #27170 Show the deprecations tab by default in the logger panel (javiereguiluz)
* feature #27130 [Messenger] Add a new time limit receiver (sdelicata)
* feature #27104 [DX] Redirect to proper Symfony version documentation (noniagriconomie)
* feature #27105 [Serializer] Add ->hasCacheableSupportsMethod() to CacheableSupportsMethodInterface (nicolas-grekas)
* feature #24896 Add CODE_OF_CONDUCT.md (egircys)
* feature #27092 [Workflow] "clear()" instead of "reset()" (nicolas-grekas)
* feature #26655 [WebProfilerBundle] Make WDT follow ajax requests if header set (jeffreymb)
* feature #27049 [Serializer] Cache the normalizer to use when possible (dunglas, nicolas-grekas)
* feature #27062 [SecurityBundle] Register a `UserProviderInterface` alias if one provider only (sroze)
* feature #27065 [DI][Routing] Allow invokable objects to be used as PHP-DSL loaders (aurimasniekis)
* feature #26975 [Messenger] Add a memory limit option for `ConsumeMessagesCommand` (sdelicata)
* feature #26864 [Messenger] Define multiple buses from the `framework.messenger.buses` configuration (sroze)
* feature #27017 [Serializer] Allow to access to the context and various other infos in callbacks and max depth handler (dunglas)
* feature #26832 [MonologBridge] Added WebSubscriberProcessor to ease processor configuration (lyrixx)
* feature #24699 [HttpFoundation] Add HeaderUtils class (c960657)
* feature #26791 [BrowserKit] Bypass Header Informations (cfjulien)
* feature #26825 [Form] Add choice_translation_locale option for Intl choice types (yceruto, fabpot)
* feature #26921 [DI][FrameworkBundle] Hide service ids that start with a dot (nicolas-grekas)
* feature #23659 [HttpKernel] LoggerDataCollector: splitting logs on different sub-requests (vtsykun)
* feature #26768 [DI] Allow autoconfigured calls in PHP (Gary PEGEOT, GaryPEGEOT)
* feature #26833 [HttpKernel] Added support for timings in ArgumentValueResolvers (iltar)
* feature #26770 Do not normalize array keys in twig globals (lstrojny)
* feature #26787 [Security] Make security.providers optional (MatTheCat)
* feature #26970 [VarDumper] Add dd() helper == dump() + exit() (nicolas-grekas)
* feature #26941 [Messenger] Allow to configure the transport (sroze)
* feature #26632 [Messenger] Add AMQP adapter (sroze)
* feature #26863 [Console] Support iterable in SymfonyStyle::write/writeln (ogizanagi)
* feature #26847 [Console] add support for iterable in output (Tobion)
* feature #26660 [SecurityBundle] allow using custom function inside allow_if expressions (dmaicher)
* feature #26096 [HttpFoundation] Added a migrating session handler (rossmotley)
* feature #26528 [Debug] Support any Throwable object in FlattenException (derrabus)
* feature #26811 [PhpUnitBridge] Search for other SYMFONY_* env vars in phpunit.xml then phpunit.xml.dist (lyrixx)
* feature #26800 [PhpUnitBridge] Search for SYMFONY_PHPUNIT_REMOVE env var in phpunit.xml then phpunit.xml.dist (lyrixx)
* feature #26684 [Messenger] Remove the Doctrine middleware configuration from the FrameworkBundle (sroze)
* feature #21856 [LDAP] Allow adding and removing values to/from multi-valued attributes (jean-gui)
* feature #26767 [Form] ability to set rounding strategy for MoneyType (syastrebov)
* feature #23707 [Monolog Bridge][DX] Add a Monolog activation strategy for ignoring specific HTTP codes (simshaun, fabpot)
* feature #26685 [Messenger] Add a `MessageHandlerInterface` (multiple messages + auto-configuration) (sroze)
* feature #26648 [Messenger] Added a middleware that validates messages (Nyholm)
* feature #26475 [HttpFoundation] split FileException into specialized ones about upload handling (fmata)
* feature #26702 Mark ExceptionInterfaces throwable (ostrolucky)
* feature #26656 [Workflow][Registry] Added a new 'all' method (alexpozzi, lyrixx)
* feature #26693 [Console] Add box-double table style (maidmaid)
* feature #26698 [Console] Use UTF-8 bullet for listing (ro0NL)
* feature #26682 Improved the lint:xliff command (javiereguiluz)
* feature #26681 Allow to easily ask Symfony not to set a response to private automatically (Toflar)
* feature #26627 [DI] Add runtime service exceptions to improve the error message when controller arguments cannot be injected (nicolas-grekas)
* feature #26504 [FrameworkBundle] framework.php_errors.log now accept a log level (Simperfit)
* feature #26498 Allow "json:" env var processor to accept null value (mcfedr)
* feature #25928 [DI] Allow binary values in parameters. (bburnichon)
* feature #26647 [Messenger] Add a middleware that wraps all handlers in one Doctrine transaction. (Nyholm)
* feature #26668 [WebProfilerBundle] Live duration of AJAX request (ostrolucky)
* feature #26650 [Messenger] Clone messages to show in profiler (Nyholm)
* feature #26281 [FrameworkBundle] keep query in redirect (Simperfit)
* feature #26665 Improved the Ajax profiler panel when there are exceptions (javiereguiluz)
* feature #26654 [VarDumper] Provide binary, allowing to start a server at any time (ogizanagi)
* feature #26332 Add a data_help method in Form (mpiot, Nyholm)
* feature #26671 More compact display of vendor code in exception pages (javiereguiluz)
* feature #26502 [Form] Add Bootstrap 4 style for field FileType (zenmate)
* feature #23888 [DI] Validate env vars in config (ro0NL)
* feature #26658 Adding support to bind scalar values to controller arguments (weaverryan)
* feature #26651 [Workflow] Added a TransitionException (andrewtch, lyrixx)
* feature #23831 [VarDumper] Introduce a new way to collect dumps through a server dumper (ogizanagi, nicolas-grekas)
* feature #26220 [HttpFoundation] Use parse_str() for query strings normalization (nicolas-grekas)
* feature #24411 [Messenger] Add a new Messenger component (sroze)
* feature #22150 [Serializer] Added a ConstraintViolationListNormalizer (lyrixx)
* feature #26639 [SecurityBundle] Added an alias from RoleHierarchyInterface to security.role_hierarchy (lyrixx)
* feature #26636 [DI] deprecate TypedReference::canBeAutoregistered() and getRequiringClass() (nicolas-grekas)
* feature #26445 [Serializer] Ignore comments when decoding XML (q0rban)
* feature #26284 [Routing] allow no-slash root on imported routes (nicolas-grekas)
* feature #26092 [Workflow] Add a MetadataStore to fetch some metadata (lyrixx)
* feature #26121 [FrameworkBundle] feature: add the ability to search a route (Simperfit)
* feature #25197 [FrameworkBundle][TwigBridge] make csrf_token() usable without forms (xabbuh)
* feature #25631 [DI] Service decoration: autowire the inner service (dunglas)
* feature #26076 [Workflow] Add transition blockers (d-ph, lyrixx)
* feature #24363 [Console] Modify console output and print multiple modifyable sections (pierredup)
* feature #26381 Transform both switchToXHR() and removeXhr() to xmlHttpRequest() (Simperfit)
* feature #26449 Make ProgressBar::setMaxSteps public (ostrolucky)
* feature #26308 [Config] Introduce BuilderAwareInterface (ro0NL)
* feature #26518 [Routing] Allow inline definition of requirements and defaults (nicolas-grekas)
* feature #26143 [Routing] Implement i18n routing (frankdejonge, nicolas-grekas)
* feature #26564 [HttpFoundation] deprecate call to Request::getSession() when Request::hasSession() returns false (fmata)
* feature #26408 Readd 'form_label_errors' block to disable errors on form labels (birkof)
* feature #25456 [Console] Make pretty the `box` style table (maidmaid)
* feature #26499 [FrameworkBundle] Allow fetching private services from test clients (nicolas-grekas)
* feature #26509 [BrowserKit] Avoid nullable values in some Client's methods (ossinkine)
* feature #26288 [FrameworkBundle] show the unregistered command warning at the end of the list command (Simperfit)
* feature #26520 Added some HTML5 features to the Symfony Profiler (javiereguiluz)
* feature #26398 [WebProfilerBundle] Display the missing translation panel by default (javiereguiluz)
* feature #23409 [Security] AuthenticationUtils::getLastUsername() return type inconsistency (vudaltsov)
* feature #26439 [Console] [DX] Fix command description/help display (noniagriconomie)
* feature #26372 Revert "feature #24763 [Process] Allow writing portable "prepared" command lines (Simperfit)" (nicolas-grekas)
* feature #26223 [FrameworkBundle] Add command to delete an item from a cache pool (pierredup)
* feature #26341 Autoconfigure service locator tag (apfelbox)
* feature #26330 [FORM] Fix HTML errors. (Nyholm)
* feature #26334 [SecurityBundle] Deprecate switch_user.stateless config node (chalasr)
* feature #26304 [Routing] support scheme requirement without redirectable dumped matcher (Tobion)
* feature #26283 [Routing] Redirect from trailing slash to no-slash when possible (nicolas-grekas)
* feature #25732 [Console] Add option to automatically run suggested command if there is only 1 alternative (pierredup)
* feature #26085 Deprecate bundle:controller:action and service:method notation (Tobion)
* feature #26175 [Security] Add configuration for Argon2i encryption (CoalaJoe)
* feature #26075 [Validator] Deprecate use of `Locale` validation constraint without setting "canonicalize" option to `true` (phansys)
* feature #26218 [MonologBridge] Allow to change level format in ConsoleFormatter (ostrolucky)
* feature #26232 [Lock] Add a TTL to refresh lock (jderusse)
* feature #26108 [Serializer] Add a MaxDepth handler (dunglas)
* feature #24778 [BrowserKit] add a way to switch to ajax for one request (Simperfit)
* feature #25605 [PropertyInfo] Added support for extracting type from constructor (lyrixx)
* feature #24763 [Process] Allow writing portable "prepared" command lines (Simperfit)
* feature #25218 [Serializer] add a constructor arguement to return csv always as collection (Simperfit)
* feature #25369 [Serializer] add a context key to return always as collection for XmlEncoder (Simperfit)
* feature #26213 [FrameworkBundle] Add support to 307/308 HTTP status codes in RedirectController (ZipoKing)
* feature #26149 Added support for name on the unit node (Nyholm)
* feature #24308 [Validator] support protocolless urls validation (MyDigitalLife)
* feature #26059 [Routing] Match 77.7x faster by compiling routes in one regexp (nicolas-grekas)
* feature #22447 [WebProfilerBundle] Imply forward request by a new X-Previous-Debug-Token header (ro0NL)
* feature #26152 [Intl] Add polyfill for Locale::canonicalize() (nicolas-grekas)
* feature #26073 [DoctrineBridge] Add support for datetime immutable types in doctrine type guesser (jvasseur)
* feature #26079 [Workflow] Remove constraints on transition/place name + Updated Dumper (lyrixx)
* feature #23617 [PropertyInfo] Add hassers for accessors prefixes (sebdec)
* feature #25997 Always show all deprecations except legacy ones when not weak (greg0ire)
* feature #25582 [Form] Support \DateTimeImmutable (vudaltsov)
* feature #24705 [Workflow] Add PlantUML dumper to workflow:dump command (Plopix)
* feature #24508 [Serializer] Fix security issue on CsvEncoder about CSV injection (welcoMattic)
* feature #25772 [Security] The AuthenticationException should implements Security's ExceptionInterface (sroze)
* feature #25164 [WebProfilerBundle] Improve controller linking (ro0NL)
* feature #22353 [Validator] Add `canonicalize` option for `Locale` validator (phansys)
* feature #26036 Added support for getting default values in Accept headers (javiereguiluz)
* feature #25780 [TwigBundle] Deprecating "false" in favor of "kernel.debug" as default value of "strict_variable" (yceruto)
* feature #23508 Deprecated the AdvancedUserInterface (iltar)
* feature #24781 [HttpFoundation] RedisSessionHandler (dkarlovi)
* feature #26028 Unwrap errors in FlattenException (derrabus)
* feature #25892 Adding an array adapter (weaverryan)
* feature #24894 [FrameworkBundle] add a notice when passing a routerInterface without warmupInterface in RouterCacheWarmer (Simperfit)
* feature #24632 [DependencyInjection] Anonymous services in PHP DSL (unkind)
* feature #25836 [HttpKernel] Make session-related services extra-lazy (nicolas-grekas)
* feature #25775 Introduce signaled process specific exception class (Soullivaneuh)
* feature #22253 [Config] allow changing the path separator (bburnichon)
* feature #25493 [Serializer] `default_constructor_arguments` context option for denormalization (Nek-)
* feature #25839 [SecurityBundle] Deprecate in_memory.user abstract service (chalasr)
* feature #24392 Display orphaned events in profiler (kejwmen)
* feature #25275 [DI] Allow for invokable event listeners (ro0NL)
* feature #25627 [DI] Add a simple CSV env var processor (dunglas)
* feature #25092 [Security] #25091 add target user to SwitchUserListener (jwmickey)
* feature #24777 [TwigBundle] Added priority to twig extensions (Brunty)
* feature #25710 [FrameworkBundle] add cache.app.simple psr simple cache (dmaicher)
* feature #25669 [Security] Fail gracefully if the security token cannot be unserialized from the session (thewilkybarkid)
* feature #25504 [Validator] Add option to pass custom values to Expression validator (ostrolucky)
* feature #25701 [FrameworkBundle] add autowiring aliases for TranslationReaderInterface, ExtractorInterface & TranslationWriterInterface (Dennis Langen)
* feature #25516 [Validator] Deprecated "checkDNS" option in Url constraint (ro0NL)
* feature #25588 Move SecurityUserValueResolver to security-http (chalasr)
* feature #25629 [Process] Make `PhpExecutableFinder` look for the `PHP_BINARY` env var (nicolas-grekas)
* feature #25562 allow autowire for http_utils class (do-see)
* feature #25478 [FrameworkBundle] add email_validation_mode option (xabbuh)
* feature #25366 [HttpKernel] Decouple exception logging from rendering (ro0NL)
* feature #25450 [PropertyAccess] add more information to NoSuchPropertyException Message (Simperfit)
* feature #25148 Pr/workflow name as graph label (shdev)
* feature #25324 [HttpFoundation] Incorrect documentation and method name for UploadedFile::getClientSize() (Simperfit)
* feature #24738 [FrameworkBundle][Routing] Use a PSR-11 container in FrameworkBundle Router (ogizanagi)
* feature #25439 Add ControllerTrait::getParameter() (chalasr)
* feature #25332 [VarDumper] Allow VarDumperTestTrait expectation to be non-scalar (romainneutron)
* feature #25301 [Console] Add box style table (maidmaid)
* feature #25415 [FrameworkBundle] Add atom editor to ide config (lexcast)
* feature #24442 [Validator] Html5 Email Validation (PurpleBooth)
* feature #25288 [DI][FrameworkBundle] Add PSR-11 "ContainerBag" to access parameters as-a-service (nicolas-grekas, sroze)
* feature #25290 [FrameworkBundle] debug:autowiring: don't list FQCN when they are aliased (nicolas-grekas)
* feature #24375 [Serializer] Serialize and deserialize from abstract classes (sroze)
* feature #25346 [DoctrineBridge] DoctrineDataCollector comments the non runnable part of the query (Simperfit)
* feature #24216 added clean option to assets install command (robinlehrmann)
* feature #25142 [Process] Create a "isTtySupported" static method (nesk)
* feature #24751 [Workflow] Introduce a Workflow interface (Simperfit)
* feature #25293 [Routing] Parse PHP constants in YAML routing files (ostrolucky)
* feature #25295 [Translation] Parse PHP constants in YAML translation files (ostrolucky)
* feature #25294 [Serializer] Parse PHP constants in YAML mappings (ostrolucky)
* feature #24637 [FrameworkBundle] Improve the DX of TemplateController when using SF 4 (dunglas)
* feature #25178 [Routing] Allow to set name prefixes from the configuration (sroze)
* feature #25237 [VarDumper] add a GMP caster in order to cast GMP resources into string or integer (Simperfit)
* feature #25166 [WebProfilerBundle] Expose dotenv variables (ro0NL)
* feature #24785 [Profiler][Translation] Logging false by default and desactivated when using the profiler (Simperfit)
* feature #24826 [FrameworkBundle] Allow to pass a logger instance to the Router (ogizanagi)
* feature #24937 [DependencyInjection] Added support for variadics in named arguments (PabloKowalczyk)
* feature #24819 [Console] add setInputs to ApplicationTester and share some code (Simperfit)
* feature #25131 [SecurityBundle][Security][Translation] trigger some deprecations for legacy methods (xabbuh)

View File

@ -0,0 +1,604 @@
CHANGELOG for 4.2.x
===================
This changelog references the relevant changes (bug and security fixes) done
in 4.2 minor versions.
To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash
To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v4.2.0...v4.2.1
* 4.2.8 (2019-05-01)
* bug #31338 Revert "bug #30620 [FrameworkBundle][HttpFoundation] make session service resettable (dmaicher)" (nicolas-grekas)
* bug #31326 fix ConsoleFormatter - call to a member function format() on string (keksa)
* bug #31331 [Workflow] Fixed dumping when many transition with same name exist (lyrixx)
* bug #31302 [FramworkBundle] mark any env vars found in the ide setting as used (nicolas-grekas)
* bug #31290 [TwigBundle] Use the apply tag instead of the filter tag (greg0ire)
* bug #31275 [Translator] Preserve default domain when extracting strings from php files (Stadly)
* bug #31240 Fix url matcher edge cases with trailing slash (arjenm)
* bug #31201 [Form] resolve class name parameters (xabbuh)
* bug #31213 [WebProfilerBundle] Intercept redirections only for HTML format (javiereguiluz)
* bug #31210 [PhpUnitBridge] fix reading phpunit.xml on bootstrap (nicolas-grekas)
* bug #31023 [Routing] Fix route URL generation in CLI context (X-Coder264)
* bug #31117 [FrameworkBundle] fix math depth handler configuration (Raulnet)
* bug #31182 [Routing] fix trailing slash matching with empty-matching trailing vars (nicolas-grekas)
* bug #31167 [Routing] fix matching trailing vars with defaults (nicolas-grekas)
* bug #31164 [Validator] fix LegacyTranslatorProxy (nicolas-grekas)
* bug #31156 [FrameworkBundle] call method with Translator component only (xabbuh)
* 4.2.7 (2019-04-17)
* bug #31107 [Routing] fix trailing slash redirection with non-greedy trailing vars (nicolas-grekas)
* bug #31108 [FrameworkBundle] decorate the ValidatorBuilder's translator with LegacyTranslatorProxy (nicolas-grekas)
* bug #31121 [HttpKernel] Fix get session when the request stack is empty (yceruto)
* bug #31084 [HttpFoundation] Make MimeTypeExtensionGuesser case insensitive (vermeirentony)
* bug #31142 Revert "bug #30423 [Security] Rework firewall's access denied rule (dimabory)" (chalasr)
* security #cve-2019-10910 [DI] Check service IDs are valid (nicolas-grekas)
* security #cve-2019-10909 [FrameworkBundle][Form] Fix XSS issues in the form theme of the PHP templating engine (stof)
* security #cve-2019-10912 [Cache][PHPUnit Bridge] Prevent destructors with side-effects from being unserialized (nicolas-grekas)
* security #cve-2019-10911 [Security] Add a separator in the remember me cookie hash (pborreli)
* security #cve-2019-10913 [HttpFoundation] reject invalid method override (nicolas-grekas)
* 4.2.6 (2019-04-16)
* bug #31088 [DI] fix removing non-shared definition while inlining them (nicolas-grekas)
* bug #29944 [DI] Overriding services autowired by name under _defaults bind not working (przemyslaw-bogusz, renanbr)
* bug #30993 [FrameworkBundle] Fix for Controller DEPRECATED when using composer --optimized (aweelex)
* bug #31076 [HttpKernel] Fixed LoggerDataCollector crashing on empty file (althaus)
* bug #31071 property normalizer should also pass format and context to isAllowedAttribute (dbu)
* bug #31059 Show more accurate message in profiler when missing stopwatch (linaori)
* bug #31026 [Serializer] Add default object class resolver (jdecool)
* bug #31031 [Serializer] MetadataAwareNameConverter: Do not assume that property names are strings (soyuka)
* bug #31043 [VarExporter] support PHP7.4 __serialize & __unserialize (nicolas-grekas)
* bug #30423 [Security] Rework firewall's access denied rule (dimabory)
* bug #31020 [VarExporter] fix exporting classes with private constructors (nicolas-grekas)
* bug #31012 [Process] Fix missing $extraDirs when open_basedir returns (arsonik)
* bug #30852 [Console] fix buildTableRows when Colspan is use with content too long (Raulnet)
* bug #30950 [Serializer] Also validate callbacks when given in the normalizer context (dbu)
* bug #30907 [Serializer] Respect ignored attributes in cache key of normalizer (dbu)
* bug #30085 Fix TestRunner compatibility to PhpUnit 8 (alexander-schranz)
* bug #30999 Fix dark themed componnents (ro0NL)
* bug #30977 [serializer] prevent mixup in normalizer of the object to populate (dbu)
* bug #30976 [Debug] Fixed error handling when an error is already handled when another error is already handled (5) (lyrixx)
* bug #30979 Fix the configurability of CoreExtension deps in standalone usage (stof)
* bug #30918 [Cache] fix using ProxyAdapter inside TagAwareAdapter (dmaicher)
* bug #30961 [Form] fix translating file validation error message (xabbuh)
* bug #30951 Handle case where no translations were found (greg0ire)
* bug #29800 [Validator] Only traverse arrays that are cascaded into (corphi)
* bug #30921 [Translator] Warm up the translations cache in dev (tgalopin)
* bug #30922 [TwigBridge] fix horizontal spacing of inlined Bootstrap forms (xabbuh)
* bug #30860 [Profiler] Fix dark theme elements color (dFayet)
* bug #30895 [Form] turn failed file uploads into form errors (xabbuh)
* bug #30919 [Translator] Fix wrong dump for PO files (deguif)
* bug #30889 [DependencyInjection] Fix a wrong error when using a factory (Simperfit)
* bug #30911 [Console] Fix table trailing backslash (maidmaid)
* bug #30903 [Messenger] Uses the `SerializerStamp` when deserializing the envelope (sroze)
* bug #30879 [Form] Php doc fixes and cs + optimizations (Jules Pietri)
* bug #30883 [Console] Fix stty not reset when aborting in QuestionHelper::autocomplete() (Simperfit)
* bug #30878 [Console] Fix inconsistent result for choice questions in non-interactive mode (chalasr)
* bug #30825 [Routing] Fix: annotation loader ignores method's default values (voronkovich)
* 4.2.5 (2019-04-02)
* bug #30660 [Bridge][Twig] DebugCommand - fix escaping and filter (SpacePossum)
* bug #30784 [Translator] Add resource path to exception message for schema valida… (jschaedl)
* bug #30720 Fix getSetMethodNormalizer to correctly ignore the attributes specified in "ignored_attributes" (Emmanuel BORGES)
* bug #30749 [Serializer] Added check of constuctor modifiers to AbstractNormalizer (NekaKawaii)
* bug #30776 [Routing] Fix routes annotation loading with glob pattern (snoob)
* bug #30773 [DependencyInjection] Fix hardcoded hotPathTagName (jderusse)
* bug #30737 [Validator] Improve constraint default option check (vudaltsov)
* bug #30736 [Validator] Fix annotation default for @Count and @Length (vudaltsov)
* bug #30621 [Cache] Ensure key exists before checking array value (jrjohnson)
* bug #30711 [Serializer] Use object class resolver when extracting attributes (joelwurtz)
* bug #30641 [FrameworkBundle] properly describe service definitions without class (xabbuh)
* bug #30620 [FrameworkBundle][HttpFoundation] make session service resettable (dmaicher)
* bug #30648 Debug finalized config in debug:config (ro0NL)
* bug #30640 [Phpunit] fixed support for PHP 5.3 (fabpot)
* bug #30616 Fix case when multiple loaders are providing paths for the same namespace (yceruto)
* bug #30595 Do not validate child constraints if form has no validation groups (maryo)
* bug #30440 [TwigBridge] Fix DebugCommand when chain loader is involved (yceruto)
* bug #30479 Check if Client exists when test.client does not exist, to provide clearer exception message (SerkanYildiz)
* bug #30597 [Form] Added ResetInterface to CachingFactoryDecorator (HeahDude)
* bug #30593 Fixed usage of TranslatorInterface in form extension (fixes #30591) (althaus)
* feature #30584 [Intl] Add compile binary (ro0NL)
* bug #30487 Fix Cache error while using anonymous class (Emmanuel BORGES)
* bug #30576 [Cache] fix LockRegistry (nicolas-grekas)
* bug #30548 Correct language code for ukrainian language (stanleyk)
* bug #30518 [Cache] Fix perf when using RedisCluster by reducing roundtrips to the servers (nicolas-grekas)
* bug #30515 [Cache] Only delete one key at a time when on Predis + Cluster (andrerom)
* bug #30511 [Process] fix using argument $php of new PhpProcess() (nicolas-grekas)
* bug #30507 [Routing] Fixed XML options resolution (Jules Pietri)
* bug #30506 [TwigBridge] remove deprecation triggered when using Twig 2.7 (nicolas-grekas)
* bug #30496 [PHPUnit-Bridge] override some Composer environment variables (nicoweb)
* bug #30505 [TwigBridge] Remove usages of the spaceless tag (nicolas-grekas)
* bug #30466 [Messenger] Make 'headers' key optional for encoded messages (yceruto)
* bug #30474 compatibility with phpunit8 (garak)
* bug #30497 [HttpKernel] Change default log level for output streams (yceruto)
* bug #30498 [translation] Update defaut format from yml to yaml (GaryPEGEOT)
* bug #30490 Don't resolve the Deprecation error handler mode until a deprecation is triggered (Emmanuel BORGES)
* bug #30396 [Form] Avoid a form type extension appears many times in debug:form (markitosgv)
* bug #30361 [PropertyInfo] Fix undefined variable fromConstructor when passing context to getTypes (mantis)
* bug #30361 [PropertyInfo] Fix undefined variable fromConstructor when passing context to getTypes (mantis, OskarStark)
* bug #30410 [Monolog] Really reset logger when calling logger::reset() (lyrixx)
* bug #30437 [Debug] detect annotations before blank docblock lines (xabbuh)
* bug #30417 Autoconfig: don't automatically tag decorators (dunglas)
* bug #30392 [PropertyAccess] Fixed PropertyPathBuilder remove that fails to reset internal indexes (GregOriol)
* 4.2.4 (2019-03-03)
* bug #30383 [WebProfilerBundle] toolbar: invisible route name in Firefox (inmarelibero)
* bug #26532 [HttpKernel] Correctly merging cache directives in HttpCache/ResponseCacheStrategy (aschempp)
* bug #30363 Fixed the DebugClassLoader compatibility with eval()'d code on Darwin (skalpa)
* bug #30329 [Form] IntegerType: reject submitted non-integer numbers (xabbuh)
* bug #30331 [Cache] fix warming up cache.system and apcu (nicolas-grekas)
* bug #30347 [Security] Change FormAuthenticator if condition (PReimers)
* bug #30354 [Console] handles multi-byte characters in autocomplete (jls-esokia)
* bug #30351 Fix getItems() performance issue with RedisCluster (php-redis) (andrerom)
* bug #30350 [VarDumper] Keep a ref to objects to ensure their handle cannot be reused while cloning (nicolas-grekas)
* bug #30327 [HttpKernel] Fix possible infinite loop of exceptions (enumag)
* bug #27601 [Routing] fix URL generation with look-around requirements (nasimnabavi)
* bug #30277 [Console] Prevent ArgvInput::getFirstArgument() from returning an option value (chalasr)
* bug #29981 [Security] Complain about an empty decision strategy (corphi)
* bug #29822 [EventDispatcher] Fix unknown priority (ro0NL)
* bug #30324 [Validator] Fixed duplicate UUID (ralfkuehnel)
* bug #30265 [Form] do not validate non-submitted form fields in PATCH requests (xabbuh)
* bug #30313 Avoid mutating the Finder when building the iterator (stof)
* bug #30294 [FrameworkBundle] Fix Descriptor throwing on non existent parent (GuilhemN)
* bug #30271 [Console] Fix command testing with missing user inputs (chalasr)
* bug #30278 Remove unnecessary ProgressBar stdout writes (fixes flickering) (ostrolucky)
* bug #30274 [VarDumper] fix serializing Stub instances (nicolas-grekas)
* bug #30273 [Validator] Added missing use statement for UnexpectedTypeException (devrck)
* bug #30247 Don't resolve the Deprecation error handler mode until a deprecation is triggered (ossinkine)
* bug #30264 [Debug][ErrorHandler] Preserve next error handler (fancyweb)
* bug #30245 fix lost namespace in eval (fizzka)
* bug #30090 [FrameworkBundle] add constraint validators before optimizations (xabbuh)
* feature #30126 [Form] forward valid numeric values to transform() (xabbuh)
* bug #30122 [Security] fix switch user without having current token (Antoine Lamirault)
* bug #30136 use PropertyAccessorInterface instead of PropertyAccessor (nick-zh)
* bug #30124 Fix KernelTestCase compatibility for PhpUnit 8 (bis) (nicolas-grekas)
* bug #30061 [Form] render integer types with grouping as text input (xabbuh)
* bug #30063 [Form] don't lose int precision with not needed type casts (xabbuh)
* bug #30076 [Form] ignore _method forms in NativeRequestHandler (xabbuh)
* bug #30084 Fix KernelTestCase compatibility for PhpUnit 8 (alexander-schranz)
* bug #30093 [DependencyInjection] add $lazyLoad context to the generated code for lazy non-shared service by PhpDumper (XuruDragon)
* bug #30102 [Workflow] Graphviz dumper escape not always a string (Korbeil)
* bug #29884 [Form] CsrfValidationListener marks the token as invalid if it is not a string (umpirsky)
* bug #30058 [Routing] fix perf issue when dumping large number of routes (nicolas-grekas)
* bug #30062 [Form] do not overwrite the constraint being evaluated (xabbuh)
* bug #30074 Fix wrong value in file id attribute for Xliff 2.0 (deguif)
* bug #30078 [Messenger] Fix DataCollector template (ottaviano)
* bug #30087 [PhpUnitBridge] fix PHP 5.3 compat (nicolas-grekas)
* 4.2.3 (2019-02-03)
* bug #30050 [Cache] fix pruning pdo cache for vendors that throw on execute (bendavies)
* bug #30046 [DI] Fix dumping Doctrine-like service graphs (nicolas-grekas)
* bug #30028 [Form] fix some docblocks and type checks (xabbuh)
* bug #30037 Disable Twig in the profiler menu when Twig is not used (javiereguiluz)
* bug #30026 [VarDumper] dont implement Serializable in Stub (nicolas-grekas)
* bug #30034 [Config] ensure moving away from Serializable wont break cache:clear (nicolas-grekas)
* bug #29532 [Messenger] fixed RabbitMQ arguments not passed as integer values (thePanz)
* bug #30013 [Routing] dont redirect routes with greedy trailing vars with no explicit slash (nicolas-grekas)
* bug #30006 [Security] don't do nested calls to serialize() (nicolas-grekas, Renan)
* bug #30007 [FrameworkBundle] Support use of hyphen in asset package name (damaya, XuruDragon)
* bug #30004 Fix format strings for deprecation notices (TysonAndre)
* bug #29984 [VarDumper] Fixed search bar (ro0NL)
* bug #29764 [HttpFoundation] Check file exists before unlink (adam-mospan)
* bug #29783 [HttpFoundation] MemcachedSessionHandler::close() must close connection (grachevko)
* bug #29794 Always pass $key to NullAdapter->createCacheItem (TysonAndre)
* bug #29844 [Console] Fixed #29835: ConfirmationQuestion with default true for answer '0' (mrthehud)
* bug #29869 [Debug][ErrorHandler] Preserve our error handler when a logger sets another one (fancyweb)
* bug #29900 [Cache] PDO-based cache pool table autocreation does not work (errogaht)
* bug #29926 [Form] Changed UrlType input type to text when default_protocol is not null (MatTheCat)
* bug #29961 [Translation] Concatenated translation messages (Stadly)
* bug #29847 [Cache] fix used variable name (xabbuh)
* bug #29920 [Debug][DebugClassLoader] Match more cases for final, deprecated and internal classes / methods extends (fancyweb)
* bug #29922 Avoid dots in generated class names (derrabus)
* bug #29863 [Security] Do not mix password_*() API with libsodium one (chalasr)
* bug #29894 [DependencyInjection] the string "0" is a valid service identifier (xabbuh)
* bug #29885 Update MimeType extensions (fabpot)
* bug #29875 [TwigBridge] fix compatibility with Twig >= 2.6.1 (xabbuh)
* bug #29873 [Debug] remove return type hint for PHP 5 compatibility (xabbuh)
* bug #29837 Fix SwiftMailerHandler to support Monolog's latest reset functionality (Seldaek)
* bug #29853 Revert "bug #29597 [DI] fix reporting bindings on overriden services as unused" (mmarynich)
* bug #29833 [DebugClassLoader] expose proxyfied findFile() method (fancyweb)
* 4.2.2 (2019-01-06)
* bug #29494 [HttpFoundation] Fix request uri when it starts with double slashes (alquerci)
* bug #29697 [DI] Fixed wrong factory method in exception (Wojciech Gorczyca)
* bug #29679 [HttpKernel] Correctly Render Signed URIs Containing Fragments (zanbaldwin)
* bug #29754 Ensure final input of CommandTester works with default (Firehed)
* bug #29695 [Form] Do not ignore the choice groups for caching (vudaltsov)
* bug #29738 [Intl] handle null date and time types (xabbuh)
* bug #29708 [FrameworkBundle] access the container getting it from the kernel (xabbuh)
* bug #29676 [HttpFoundation] Fix erasing cookies issue (eiannone)
* bug #29741 [VarExporter] fix exporting array indexes (xabbuh)
* bug #29704 [FrameworkBundle] improve errors in tests missing the BrowserKit component (xabbuh)
* bug #29721 [SecurityBundle] Fix traceable voters (ro0NL)
* bug #29617 [Console] Add specific replacement for help text in single command applications (codedmonkey)
* bug #29714 [Event Dispatcher] fixed 29703: TraceableEventDispatcher reset() callStack to null (mlievertz)
* bug #29597 [DI] fix reporting bindings on overriden services as unused (nicolas-grekas)
* bug #29639 [Yaml] detect circular references (xabbuh)
* bug #29644 [Cache] fix bad optim (nicolas-grekas)
* bug #29648 [Cache] fix Simple\Psr6Cache proxying of metadata (nicolas-grekas)
* bug #29569 [FrameworkBundle] decouple debug:autowiring from phpdocumentor/reflection-docblock (SerkanYildiz)
* bug #29546 [DI] map snake-case ids of service subscribers to camel-case autowiring aliases (nicolas-grekas)
* bug #29409 Fix env fallback to an unresolved variable (jderusse)
* bug #29626 [Routing] fix trailing slash redirections involving a trailing var (nicolas-grekas)
* bug #29411 [EventDispatcher] Revers event tracing order (ro0NL)
* bug #29533 Fixed public directory when configured in composer.json (alexander-schranz)
* bug #29619 [Console] OutputFormatter: move strtolower to createStyleFromString (ogizanagi)
* bug #29621 [Security] Prefer clone() over unserialize(serialize()) for user refreshment (chalasr)
* bug #29591 [Cache] Fix undefined variable in ArrayTrait (eXtreme)
* bug #29558 [Messenger] Restore message handlers laziness (chalasr)
* bug #29589 [VarExporter] dont call userland code with uninitialized objects (nicolas-grekas)
* bug #29542 [Routing] fix dumping same-path routes with placeholders (nicolas-grekas)
* bug #29587 [Debug] ignore underscore vs backslash namespaces in DebugClassLoader (nicolas-grekas)
* bug #29584 [FrameworkBundle] fix describing routes with no controllers (nicolas-grekas)
* bug #29582 [DI] move RegisterServiceSubscribersPass before DecoratorServicePass (kbond)
* bug #29527 [TwigBridge][Form] Prevent multiple rendering of form collection prototypes (Shoplifter)
* bug #29571 [Yaml] ensures that the mb_internal_encoding is reset to its initial value (Jörn Lang)
* bug #29513 [Hackday][Serializer] Deserialization ignores argument type hint from phpdoc for array in constructor argument (karser)
* bug #29323 [Security] defer log message in guard authenticator (eschultz-magix)
* bug #29539 [WebProfilerBundle][TwigBundle] CSS fixes (ro0NL)
* bug #29543 [Cache] Don't erase processed redis dsn (chalasr)
* bug #29531 [Validator] Added IBAN format for Vatican City State (raulfraile)
* bug #29501 [Form] filter out invalid language values (xabbuh)
* bug #29307 [Form] Filter arrays out of scalar form types (nicolas-grekas)
* bug #29500 [Form] filter out invalid Intl values (xabbuh)
* bug #29499 [Validator] Fixed grouped composite constraints (HeahDude)
* 4.2.1 (2018-12-06)
* security #cve-2018-19790 [Security\Http] detect bad redirect targets using backslashes (xabbuh)
* security #cve-2018-19789 [Form] Filter file uploads out of regular form types (nicolas-grekas)
* bug #29481 [TwigBridge] Deprecating legacy Twig paths in DebugCommand and simplifications (yceruto)
* bug #29436 [Cache] Fixed Memcached adapter doClear()to call flush() (raitocz)
* bug #29482 Fixes sprintf(): Too few arguments in MessageFormatter::choiceFormat (stephanedelprat)
* bug #29461 [Contracts] extract LocaleAwareInterface out of TranslatorInterface (nicolas-grekas)
* bug #29446 [VarExporter] fix dumping private properties from abstract classes (nicolas-grekas)
* bug #29441 [Routing] ignore trailing slash for non-GET requests (nicolas-grekas)
* bug #29445 [FrameworkBundle] Fix empty output for debug:autowiring when reflection-docblock is not installed (chalasr)
* bug #29444 [Workflow] Fixed BC break for Workflow metadata (lyrixx)
* bug #29432 [DI] dont inline when lazy edges are found (nicolas-grekas)
* bug #29413 [Serializer] fixed DateTimeNormalizer to maintain microseconds when a different timezone required (rvitaliy)
* bug #29424 [Routing] fix taking verb into account when redirecting (nicolas-grekas)
* bug #29418 [VarExporter] fix dumping protected property from abstract classes (nicolas-grekas)
* bug #29414 [DI] Fix dumping expressions accessing single-use private services (chalasr)
* bug #28853 [LDAP] Add TIMEOUT Option to LDAP Connection Options (lmatte7)
* bug #29399 [FrameworkBundle] define doctrine as default_pdo_provider only if the package is installed (nicolas-grekas)
* bug #29375 [Validator] Allow `ConstraintViolation::__toString()` to expose codes that are not null or emtpy strings (phansys)
* bug #29376 [EventDispatcher] Fix eventListener wrapper loop in TraceableEventDispatcher (jderusse)
* bug #29386 undeprecate the single-colon notation for controllers (fbourigault)
* bug #29393 [DI] fix edge case in InlineServiceDefinitionsPass (nicolas-grekas)
* bug #29394 [Config] fix path exclusion during glob discovery (nicolas-grekas)
* bug #29395 [FrameworkBundle][Messenger] Restore check for messenger serializer default id (ogizanagi)
* bug #29380 [Routing] fix greediness of trailing slash (nicolas-grekas)
* 4.2.0 (2018-11-30)
* bug #29343 [Form] Handle all case variants of "nan" when parsing a number (mwhudson, xabbuh)
* bug #29373 [Routing] fix trailing slash redirection (nicolas-grekas)
* bug #29355 [PropertyAccess] calculate cache keys for property setters depending on the value (xabbuh)
* bug #29369 [DI] fix combinatorial explosion when analyzing the service graph (nicolas-grekas)
* bug #29349 [Debug] workaround opcache bug mutating "$this" !?! (nicolas-grekas)
* bug #29344 Fixes sprintf(): Too few arguments in Translator (stephanedelprat)
* bug #29318 [Console] Move back root exception to stack trace in verbose mode (chalasr)
* 4.2.0-RC1 (2018-11-26)
* bug #29332 [PropertyAccess] make cache keys encoding bijective (nicolas-grekas)
* bug #29298 [Routing] fix trailing slash redirection when using RedirectableUrlMatcher (nicolas-grekas)
* bug #29297 [Routing] fix trailing slash redirection when using RedirectableUrlMatcher (nicolas-grekas)
* bug #29313 [PropertyAccessor] fix encoding of cache keys (nicolas-grekas)
* bug #29328 [HttpKernel] handle anonymous classes when generating the dumped container class name (nicolas-grekas)
* bug #28917 [DoctrineBridge] catch errors while converting to db values in data collector (alekitto)
* bug #29317 [WebProfiler] Detect non-file paths in file viewer (ro0NL)
* bug #29305 [EventDispatcher] Unwrap wrapped listeners internally (ro0NL)
* bug #29302 [Contracts][Cache] allow retrieving metadata of cached items (nicolas-grekas)
* bug #29315 [DI] fix copying expression providers when analyzing the service graph (nicolas-grekas)
* bug #27314 [DoctrineBridge] fix case sensitivity issue in RememberMe\DoctrineTokenProvider (PF4Public)
* bug #29310 [MonologBridge] Return empty list for unknown requests (ro0NL)
* bug #29316 [VarDumper] Fix ClassStub ellipsis (ro0NL)
* bug #29300 [Translation] fix dumping catalogues cache (nicolas-grekas)
* bug #29308 [Translation] Use XLIFF source rather than resname when there's no target (thewilkybarkid)
* bug #26244 [BrowserKit] fixed BC Break for HTTP_HOST header (brizzz)
* bug #28147 [DomCrawler] exclude fields inside "template" tags (Gorjunov)
* bug #29260 [Lock] Fixed PdoStore::putOffExpiration(), PdoStore::getHashedKey() (PavelPrischepa)
* bug #29222 [Dotenv] properly parse backslashes in unquoted env vars (xabbuh)
* bug #29256 [HttpFoundation] Fixed absolute Request URI with default port (thomasbisignani)
* bug #29274 [Routing] Remove duplicate schemes and methods for invokable controllers (claudusd)
* bug #29285 [HttpKernel][WebProfilerBundle] Getting the cached client mime type instead of guessing it again (yceruto)
* bug #29271 [HttpFoundation] Fix trailing space for mime-type with parameters (Sascha Dens)
* feature #29167 [Messenger] Add a trait for synchronous query & command buses (ogizanagi)
* bug #29243 [Cache] fix optimizing Psr6Cache for AdapterInterface pools (nicolas-grekas)
* bug #29247 [DI] fix taking lazy services into account when dumping the container (nicolas-grekas)
* bug #29249 [Form] Fixed empty data for compound date interval (HeahDude)
* bug #29265 [Bridge/PhpUnit] Use composer to download phpunit (nicolas-grekas)
* bug #28769 [FrameworkBundle] deal with explicitly enabled workflow nodes (xabbuh)
* 4.2.0-BETA2 (2018-11-16)
* bug #29190 [Debug][HttpKernel] remove frames added by DebugClassLoader in stack traces (nicolas-grekas)
* bug #29233 [FrameworkBundle] metadata_update_threshold default value must be an int (dunglas)
* bug #29226 [Messenger] Improved message when handler class does not exist (neeckeloo)
* bug #29223 [Validator] Added the missing constraints instance checks (thomasbisignani)
* bug #28966 [PropertyAccessor] Fix unable to write to singular property using setter while plural adder/remover exist (karser)
* bug #29182 [Form] Fixed empty data for compound date types (HeahDude)
* bug #29224 [SecurityBundle] Fix remember-me cookie framework inheritance when session is disabled (fbourigault)
* bug #29220 [Translation] make intl+icu format seamless by handling it in MessageCatalogue (nicolas-grekas)
* feature #29166 [Messenger] Add handled & sent stamps (ogizanagi)
* bug #29209 [VarExporter] fix handling of __sleep() (nicolas-grekas)
* bug #29196 [Messenger] Fix collecting messages (ro0NL)
* bug #29205 [Dotenv] skip loading "local" env twice (nicolas-grekas)
* bug #29204 [FrameworkBundle][WebServerBundle] Revert deprecation of --env and --no-debug console options (chalasr)
* bug #29191 [Routing] generate(null) should throw an exception (nicolas-grekas)
* bug #29199 [FrameworkBundle] conflict with Dotenv <4.2 to simplify recipes (nicolas-grekas)
* bug #29197 Revert "bug #29154 [FrameworkBundle] Define APP_ENV/APP_DEBUG from argv via Application::bootstrapEnv() (nicolas-grekas)
* bug #29185 [Form] Fixed keeping hash of equal \DateTimeInterface on submit (HeahDude)
* bug #29183 [HttpKernel] Fix collecting uploaded files (ro0NL)
* bug #29141 [Workflow] Fixed bug of buildTransitionBlockerList when many transition are enabled (Tetragramat, lyrixx)
* bug #29137 [Workflow][FrameworkBundle] fixed guard event names for transitions (destillat, lyrixx)
* bug #29184 [WebProfilerBundle] Fix theme settings (ro0NL)
* feature #29159 [Messenger] collect all stamps added on Envelope as collections (nicolas-grekas)
* bug #29171 [Dotenv] load .env.dist when it exists and .env is not found (nicolas-grekas)
* bug #28731 [Form] invalidate forms on transformation failures (xabbuh)
* bug #29152 [Config] Unset key during normalization (ro0NL)
* bug #29165 [DI] align IniFileLoader to PHP bugfix #76965 (nicolas-grekas)
* bug #29154 [FrameworkBundle] Define APP_ENV/APP_DEBUG from argv via Application::bootstrapEnv() (chalasr)
* bug #29129 [Dotenv] add loadEnv(), a smoother alternative to loadForEnv() (nicolas-grekas)
* bug #29113 [Routing] fix dumping conditions that use the request (nicolas-grekas)
* bug #29115 Change button_widget class to btn-primary (neFAST)
* bug #29131 [Dotenv] dont use getenv() to read SYMFONY_DOTENV_VARS (nicolas-grekas)
* bug #29057 [HttpFoundation] replace any preexisting Content-Type headers (nicolas-grekas)
* bug #29076 [Serializer] Allow null values when denormalizing with constructor missing data (danut007ro)
* bug #29128 [FrameworkBundle] Cleaning translation commands and fix a bug for --all option (yceruto)
* bug #29104 [DI] fix dumping inlined services (nicolas-grekas)
* bug #29054 [VarDumper] fix dump of closures created from callables (nicolas-grekas)
* bug #29102 [DI] fix GraphvizDumper ignoring inline definitions (nicolas-grekas)
* bug #29090 LoggingTranslator should implement Symfony\Contracts\Translation\TranslatorInterface (desmax)
* bug #29095 [TwigBridge] require the needed symfony/contracts package (xabbuh)
* bug #29107 [DI] dont track classes/interfaces used to compute autowiring error messages (nicolas-grekas)
* bug #29094 Add samesite attribute to session cookie after session migration (rpkamp)
* bug #29080 [FrameworkBundle] fix deps (ro0NL)
* 4.2.0-BETA1 (2018-11-03)
* feature #28622 [VarDumper] add caster for Memcached (jschaedl)
* feature #29042 [DI] use filter_var() instead of XmlUtils::phpize() in EnvVarProcessor (nicolas-grekas)
* feature #29047 Revert "[HttpFoundation] Adds getAcceptableFormats() method for Request" (Tobion)
* feature #29046 [Bridge/Doctrine] remove workarounds from the past (nicolas-grekas)
* feature #29022 [Cache] allow to skip saving the computed value when using CacheInterface::get() (nicolas-grekas)
* feature #29010 [Messenger] make senders and handlers subscribing to parent interfaces receive *all* matching messages, wildcard included (nicolas-grekas)
* feature #29006 [Messenger] make TraceableMiddleware decorate a StackInterface instead of each middleware to free the callstack from noisy frames (nicolas-grekas)
* feature #28970 [FrameworkBundle] make debug:autowiring list useful services and their description (nicolas-grekas)
* feature #28952 [Translation] allow using the ICU message format using domains with the "+intl-icu" suffix (nicolas-grekas)
* feature #27914 [Security][SecurityBundle] Add voter individual decisions to profiler (l-vo)
* feature #28985 [Messenger] Move MiddlewareTestCase in Test ns (ogizanagi)
* feature #28892 [FrameworkBundle] Deprecate support for legacy directories in Translation comands (chalasr)
* feature #28854 [VarDumper] Scroll into view when searching (ro0NL)
* feature #28997 [FrameworkBundle] Deprecating support for legacy translations directory (yceruto)
* feature #28983 [Messenger] make dispatch(), handle() and send() methods return Envelope (nicolas-grekas)
* feature #28533 [DotEnv] Add a new loadForEnv() method mimicking Ruby's dotenv behavior (dunglas)
* feature #28943 [Messenger] Add `StackInterface`, allowing to unstack the call stack (nicolas-grekas)
* feature #28860 [Form] Deprecate TimezoneType regions option (ro0NL)
* feature #28945 [Messenger] remove AllowNoHandlerMiddleware in favor of a constructor argument on HandleMessageMiddleware (nicolas-grekas)
* feature #28947 [Messenger] remove classifying sub-namespaces in favor of semantic ones (nicolas-grekas)
* feature #27917 [Validator] catch any UnexpectedValueException on validation (xabbuh)
* feature #28875 [FWBundle] Add a new method AbstractController::addLink() (dunglas)
* feature #28934 [WebProfilerBundle] Add channel log filter (ro0NL)
* feature #28939 [WebProfilerBundle] Remove application name (ro0NL)
* feature #28709 [Serializer] Refactor and uniformize the config by introducing a default context (dunglas)
* feature #28914 [Messenger] make Envelope first class citizen for middleware handlers (nicolas-grekas)
* feature #28909 [Messenger] made dispatch() and handle() return void (nicolas-grekas)
* feature #28936 [WebProfilerBundle] Replay referer URL (ro0NL)
* feature #28893 [TwigBundle] Fix usage of TwigBundle without FrameworkBundle (tgalopin)
* feature #28891 [TwigBundle] Deprecating support for legacy templates directories (yceruto)
* feature #28911 [Messenger] rename "envelope items" and move them in the "Stamp" namespace (nicolas-grekas)
* feature #27043 [Form][TwigBridge] Add help_attr (mpiot)
* feature #28810 [HttpKernel] Deprecate usage of getRootDir() and kernel.root_dir (fabpot)
* feature #28809 [HttpKernel] Deprecate the Kernel name (fabpot)
* feature #28807 [HttpFoundation] Make ResponseHeaderBag::makeDisposition static (fabpot)
* feature #28842 [Validator] Deprecate checkMX and checkHost on Email validator (fabpot)
* feature #28833 [Intl] Blacklist invalid languages (ro0NL)
* feature #28815 YamlEncoder handle yml format (kevin-biig)
* feature #27742 [Process] Add feature "wait until callback" to process class (Nek-)
* feature #28713 [Cache] added support for connecting to Redis clusters via DSN (nicolas-grekas)
* feature #24263 Filter logs by level (ro0NL)
* feature #24151 Display the log context in the debug pages (javiereguiluz)
* feature #26261 [Validator] Improvement: provide file basename for constr. violation messages in FileValidator. (TheCelavi)
* feature #26324 [Form] allow additional http methods in form configuration (alekitto)
* feature #26771 [Filesystem] Fix mirroring a directory with a relative path and a custom iterator (fxbt)
* feature #27291 [OptionsResolver] Added support for nesting options definition (yceruto)
* feature #27261 [VarDumper] Allow to use a light theme out of the box (ogizanagi)
* feature #27967 [Finder] Added a way to inverse a previous sorting (lyrixx)
* feature #28061 [Security] add port in access_control (roukmoute)
* feature #28476 Added different protocols to be allowed as asset base_url (alexander-schranz)
* feature #27770 [FrameworkBundle] Moving Cache-related CompilerPass to Cache component (Korbeil)
* feature #28738 [OptionsResolver] Passing Options argument to deprecation closure (yceruto)
* feature #28718 [Cache] add CacheInterface::delete() + improve CacheTrait (nicolas-grekas)
* feature #24530 [Form] simplify the form type extension registration (xabbuh)
* feature #28586 [WebServerBundle] Added ability to display the current hostname address if available when binding to 0.0.0.0 (respinoza)
* feature #28763 [WebProfilerBundle] Extract server parameters into their own tab (fabpot)
* feature #28375 [Translator] Deprecated transChoice and moved it away from contracts (Nyholm, nicolas-grekas)
* feature #28745 [WebServerBundle] Deprecate relying on --env in server:start and server:run (chalasr)
* feature #28505 [Serialized] allow configuring the serialized name of properties through metadata (fbourigault)
* feature #28669 [Serializer] Object class resolver (alanpoulain)
* feature #28653 [FrameworkBundle] Deprecate the "--env" and "--no-debug" console options (chalasr)
* feature #28693 [Security] Deprecate simple_preauth and simple_form in favor of Guard (chalasr)
* feature #28626 [Translation] marked getFallbackLocales() as internal (boscho87)
* feature #28571 [DependencyInjection] Improve ServiceLocatorTagPass service matching (codedmonkey)
* feature #28644 [Validator] Pre-check constraint validator dependencies (ro0NL)
* feature #28661 [Serializer] Add an option to skip null values (dunglas)
* feature #28679 [FrameworkBundle] Add vscode editor to ide config (lexcast)
* feature #28656 When a CSRF occures on a Form submit add a cause on the FormError object (gmponos)
* feature #28588 [Cache] add "setCallbackWrapper()" on adapters implementing CacheInterface for more flexibility (nicolas-grekas)
* feature #28598 [Cache] support configuring multiple Memcached servers in one DSN (nicolas-grekas)
* feature #28447 [HttpFoundation] make cookies auto-secure when passing them $secure=null + plan to make it and samesite=lax the defaults in 5.0 (nicolas-grekas)
* feature #28446 [SecurityBundle] make remember-me cookies auto-secure + inherit their default config from framework.session.cookie_* (nicolas-grekas)
* feature #28417 [VarExporter] add Instantiator::instantiate() to create+populate objects without calling their constructor nor any other methods (nicolas-grekas)
* feature #27819 [Serializer] deprecated normalizers and encoders who dont implement the base interfaces (rodnaph)
* feature #28572 Make it clear that the profiler is for dev only (fabpot)
* feature #28536 Favor LogicException for missing classes & functions (ro0NL)
* feature #28569 [Form] deprecate precision in IntegerToLocalizedStringTransformer (xabbuh)
* feature #28570 [Form] deprecate the unused scale option (xabbuh)
* feature #28566 [VarDumper] add casters for IntlDateFormatter and IntlCalendar (jschaedl)
* feature #28559 [VarDumper] add caster for IntlTimeZone (jschaedl)
* feature #28449 [DependencyInjection] improved message when alias service is not found (xabbuh)
* feature #27434 [Console] Add support for error ouput in the CommandTester (cdekok)
* feature #28555 [VarDumper] add caster for NumberFormatter (jschaedl)
* feature #28538 [Lock] Wrap release exception (jderusse)
* feature #28551 [VarDumper] add caster for MessageFormatter (nicolas-grekas)
* feature #28329 [Debug] Trigger a deprecation for new parameters not defined in sub classes (GuilhemN)
* feature #27920 Add Zookeeper data store for Lock Component (Ganesh Chandrasekaran)
* feature #28317 [VarDumper] Allow dd() to be called without arguments (SjorsO)
* feature #28424 [Ldap] Add verbose ext-ldap error if present for easier debugging (scaytrase)
* feature #28521 [Yaml] Added support for multiple files or directories in LintCommand (yceruto)
* feature #28522 [Translation] Added support for multiple files or directories in XliffLintCommand (yceruto)
* feature #28523 [FrameworkBundle] Register an identity translator as fallback (yceruto)
* feature #28473 [Validator] Check the BIC country with symfony/intl (sylfabre)
* feature #28487 [FrameworkBundle] Ignore backslashes in service ids when using debug:container and debug:autowiring (respinoza)
* feature #28412 [PhpUnitBridge] enable DebugClassLoader by default (nicolas-grekas)
* feature #28416 [FrameworkBundle] bind "ContainerInterface $parameterBag" arguments to the "parameter_bag" service (nicolas-grekas)
* feature #28316 Trigger deprecation notices when inherited class calls parent method but misses adding new arguments (kevinjhappy)
* feature #28373 [Console] Support max column width in Table (ro0NL)
* feature #28422 [VarExporter] throw component-specific exceptions (nicolas-grekas)
* feature #28415 [FrameworkBundle] Deprecate ContainerAwareCommand (chalasr)
* feature #28419 [Messenger] Change AmqpExt classes constructor signature (fabpot)
* feature #28405 [Messenger] Uses a messenger serializer, not an individual encoder/decoder (sroze)
* feature #28298 [WebServerBundle] Add support for Xdebug's Profiler (maidmaid)
* feature #28399 [Messenger] Add a SenderLocator decoupled from ContainerInterface (fabpot)
* feature #27321 [Messenger][Profiler] Trace middleware execution (ogizanagi)
* feature #28400 [Messenger] Add a simple serializer (fabpot)
* feature #28397 [Messenger] Change exceptions to use component's one (fabpot)
* feature #28387 [HttpKernel][Profiler] Add arg value resolver category in performances panel (ogizanagi)
* feature #25015 [Validator] Deprecate validating DateTimeInterface in Date|Time|DateTime constraints (ro0NL)
* feature #28394 [Messenger] Add interfaces to be type-hinted even when not using a Container (fabpot)
* feature #27981 [TwigBridge] Added template "name" argument to debug:twig command to find their paths (yceruto)
* feature #28207 [DI] leverage Contracts\Service (nicolas-grekas)
* feature #22225 [Console] Support formatted text cutting (ro0NL)
* feature #28206 [Contracts] Add traits+interfaces from the DI component (nicolas-grekas)
* feature #27456 [LOCK] Add a PdoStore (jderusse)
* feature #24297 Feature/doctrine type guesser simple json array support (iluuu1994)
* feature #26859 [Dotenv] add a flag to allow env vars override (fmata)
* feature #26997 [PropertyInfo] Add an extractor to guess if a property is initializable (dunglas)
* feature #27667 [Form][OptionsResolver] Show deprecated options definition on debug:form command (yceruto)
* feature #27021 [Serializer] Allow to access extra infos in name converters (dunglas)
* feature #26923 [FrameworkBundle] Allow user to specify folder for flock (MaksSlesarenko)
* feature #25125 [VarDumper] New env var to select the dump format (dunglas)
* feature #28117 [FrameworkBundle] add class description to debug:container command (gimler)
* feature #28270 [Messenger] Uses Symfony Serializer by default for envelope items (sroze)
* feature #27935 [FrameworkBundle] [Command] TranslationUpdate change default output to xlf (Alexis BOYER)
* feature #28168 Add SameSite cookies to FrameWorkBundle (rpkamp)
* feature #28303 [Process] Add relative path support for PHP_BINARY env var of PhpExecutableFinder (maidmaid)
* feature #28096 [Contracts] Add Cache contract to extend PSR-6 with tag invalidation, callback-based computation and stampede protection (nicolas-grekas)
* feature #27399 [Translation] Added intl message formatter. (aitboudad, Nyholm)
* feature #28315 [DI] Trigger exception when using '@id' name in parent option (Seb33300)
* feature #28210 [Contracts] Add Translation\TranslatorInterface + decouple symfony/validator from symfony/translation (nicolas-grekas)
* feature #28331 [FrameworkBundle] Don't populate fallback cache on warmup (nicolas-grekas)
* feature #28264 [VarDumper] make RedisCaster handle RedisCluster and dump all options on all drivers (nicolas-grekas)
* feature #28289 [Serializer] Add support for ignoring comments while XML encoding (maidmaid)
* feature #28294 [Messenger] Remove the "obscure" message subscriber configuration (sroze)
* feature #28271 [Messenger] Allow interfaces to be type-hinted as well (sroze)
* feature #28190 [Messenger] Add a --bus option to the messenger:consume-messages command (chalasr, sroze)
* feature #28275 [Messenger] Only subscribe to a given bus from the MessageSubscriber (sroze)
* feature #28243 [FrameworkBundle] Deprecate `Symfony\Bundle\FrameworkBundle\Controller\Controller` (sroze)
* feature #28070 [Translator] Use ICU parent locales as fallback locales (thewilkybarkid)
* feature #28231 [VarExporter] a new component to serialize values to plain PHP code (nicolas-grekas)
* feature #28244 [FrameworkBundle] Added new "auto" mode for `framework.session.cookie_secure` to turn it on when https is used (nicolas-grekas)
* feature #28277 [Serializer] AbstractObjectNormalizer improve performance (martiis)
* feature #28247 [Messenger] Don't make EnvelopeItemInterface extend Serializable (nicolas-grekas)
* feature #27926 [Serializer] XmlEncoder doesn't ignore PI nodes while encoding (maidmaid)
* feature #27890 Mock date() in ClockMock (Dominic Tubach)
* feature #28218 Improve support for anonymous classes (nicolas-grekas)
* feature #28221 [DomCrawler] Add a way to filter direct children (Einenlum)
* feature #28234 [DI] Allow autowiring by type + parameter name (nicolas-grekas)
* feature #28156 [Serializer] Fix the XML comments encoding (maidmaid)
* feature #28069 [Validator] New `DivisibleBy` constraint for testing divisibility (colinodell)
* feature #28176 [DI] [FrameworkBundle] Add LoggerAwareInterface to auto configuration (GaryPEGEOT)
* feature #27957 [Routing] Add fallback to cultureless locale for internationalized routes (fancyweb)
* feature #28027 [Config] Rename FileLoaderLoadException to LoaderLoadException (ProgMiner)
* feature #28085 [Config] show proposals when unsupported option is provided (fmata)
* feature #27806 [DI] Allow autoconfiguring bindings (nicolas-grekas)
* feature #21002 [Form] Added options for separate date/time labels in DateTimeType. (mktcode)
* feature #27763 [WebProfilerBundle] Append new ajax request to the end of the list (BoShurik)
* feature #28035 [DomCrawler] Allow using non-absolute base URIs (javiereguiluz)
* feature #28106 [Yaml] save preg_match() calls when possible (xabbuh)
* feature #27678 Allow to configure some options of the profiler interface (javiereguiluz)
* feature #27943 [Security] Deprecate returning stringish objects from Security::getUser (ro0NL)
* feature #27956 Added types and tweaked PHPdoc of clickLink() and submitForm() methods (javiereguiluz)
* feature #27976 [Security] Remember me: allow to set the samesite cookie flag (dunglas)
* feature #27978 [WebProfilerBundle] Show relative path of the template and improving panel view (yceruto)
* feature #27891 [Finder] Allow arrays as parameters of some methods for better fluent experience and code readability (jfredon)
* feature #27829 [DoctrineBridge] Inject the entity manager instead of the class metadata factory in DoctrineExtractor (dunglas)
* feature #27093 Add symfony/contracts: a set of abstractions extracted out of the Symfony components (nicolas-grekas)
* feature #27807 Added new methods submitForm and clickLink to Client class (nowiko)
* feature #27879 [Routing] deprecate non string requirement names (xabbuh)
* feature #26933 [Console] Add title table (maidmaid)
* feature #27697 [ProxyManagerBridge][DI] allow proxifying interfaces with "lazy: Some\ProxifiedInterface" (nicolas-grekas)
* feature #27645 [Cache] Add `MarshallerInterface` allowing to change the serializer, providing a default one that automatically uses igbinary when available (nicolas-grekas)
* feature #27694 [FrameworkBundle][Cache] Allow configuring PDO-based cache pools, with table auto-creation on first use (nicolas-grekas)
* feature #27774 [FrameworkBundle] allow turning routes to utf8 mode by default (nicolas-grekas)
* feature #27821 [Process][Console] deprecated defining commands as strings (nicolas-grekas)
* feature #27320 [Messenger] Activation middleware decorator (ogizanagi)
* feature #27519 [HttpKernel][FrameworkBundle] Turn HTTP exceptions to HTTP status codes by default (nicolas-grekas)
* feature #27020 [Serializer] Allow to access to the format and context in circular ref handler (dunglas)
* feature #27783 [DI] Add ServiceLocatorArgument to generate array-based locators optimized for OPcache shared memory (nicolas-grekas)
* feature #27850 [Security] Allow passing null as $filter in LdapUserProvider to get the default filter (louhde)
* feature #27650 [SecurityBundle] Add json login ldap (Rudy Onfroy)
* feature #27798 [Security] Use AuthenticationTrustResolver in SimplePreAuthenticationListener (nicolas-grekas)
* feature #27801 [MonologBridge] Add ProcessorInterface, enabling autoconfiguration of monolog processors (nicolas-grekas)
* feature #27503 [Serializer] Allow to pass a single value for the groups opt (dunglas)
* feature #27715 [Serializer] Deprecate CsvEncoder as_collection false default value (ogizanagi)
* feature #27768 [VarDumper] display the signature of callables (nicolas-grekas)
* feature #27766 [VarDumper] show proxified class on hover (nicolas-grekas)
* feature #27675 [DoctrineBridge] always load event listeners lazy via ServiceLocator (dmaicher)
* feature #27499 Improved an error message related to controllers (javiereguiluz)
* feature #26300 [PropertyInfo] Implement "Collection" types in PhpDocExtractor (popy-dev)
* feature #26946 [WebProfilerBundle] Display uploaded files in the profiler (javiereguiluz)
* feature #27476 [Config] deprecate tree builders without root nodes (xabbuh)
* feature #27586 [PropertyAccess] Add Property Path to Exception Message (rodnaph)
* feature #27699 Redesigned the default error page in production (javiereguiluz)
* feature #27655 [Translation] Added support for translation files with other filename patterns (javiereguiluz)
* feature #27580 [Form] Add ability to clear form errors (colinodell)
* feature #27247 [Form] Deprecate `searchAndRenderBlock` returning empty string (ostrolucky)
* feature #27646 [Cache] added support for phpredis 4 `compression` and `tcp_keepalive` options (nicolas-grekas)
* feature #27605 [DX] Log potential redirect loops caused by forced HTTPS (colinodell)
* feature #27653 [Translation] Improved the performance of the lint:xliff command (javiereguiluz)
* feature #27421 CacheWarmerAggregate handle deprecations logs (ScullWM)
* feature #27611 [FrameworkBundle][SecurityBundle] Moved security expression providers pass logic to SecurityBundle (HeahDude)
* feature #27277 [OptionsResolver] Introduce ability to deprecate options, allowed types and values (yceruto)
* feature #26919 [TwigBridge] Added bundle name suggestion on wrongly overrided templates paths (pmontoya, Pascal Montoya)
* feature #26486 [HttpFoundation] Adds getAcceptableFormats() method for Request (AndreiIgna)
* feature #27535 [TwigBundle] Enhance the twig not found exception (behnoushnorouzi)
* feature #27551 [FrameworkBundle] show public/private for aliases in debug:container command (OskarStark)
* feature #27543 [Cache] serialize objects using native arrays when possible (nicolas-grekas)
* feature #27563 [Cache] Improve perf of array-based pools (nicolas-grekas)
* feature #27604 [Cache] Prevent stampede at warmup using flock() (nicolas-grekas)
* feature #27315 [TwigBundle] add exception chain breadcrumbs navigation (kiler129)
* feature #27031 [Cache] Use sub-second accuracy for internal expiry calculations (nicolas-grekas)
* feature #27549 [Cache] Unconditionally use PhpFilesAdapter for system pools (nicolas-grekas)
* feature #27009 [Cache] Add stampede protection via probabilistic early expiration (nicolas-grekas)
* feature #27471 [DI] Improve performance of removing/inlining passes (nicolas-grekas)
* feature #27462 [FrameworkBundle] Deprecate auto-injection of the container in AbstractController instances (nicolas-grekas)
* feature #27077 [DependencyInjection] add ServiceSubscriberTrait (kbond)
* feature #27398 [Cache] Remove TaggableCacheInterface, alias cache.app.taggable to CacheInterface (nicolas-grekas)
* feature #27343 [Messenger][Profiler] Show dispatch caller (ogizanagi)
* feature #27429 [PropertyInfo] Auto-enable PropertyInfo component (sroze)
* feature #27430 [PropertyInfo] Add an alias to the property info type extractor (sroze)
* feature #27417 [WebProfilerBundle] Make Twig bundle an explicit dependency (fabpot)
* feature #27024 [Finder] added "use natural sort" option (vyshkant)
* feature #26934 [FrameworkBundle] Allow configuring taggable cache pools (nicolas-grekas)
* feature #26981 No more support for custom anon/remember tokens based on FQCN (Iltar van der Berg)
* feature #27336 [Security][SecurityBundle] FirewallMap/FirewallContext deprecations (chalasr)
* feature #27157 [DI] Select specific key from an array resolved env var (bobvandevijver)
* feature #27165 [DI] Allow binding by type+name (nicolas-grekas)
* feature #26929 [Cache] Add [Taggable]CacheInterface, the easiest way to use a cache (nicolas-grekas)
* feature #27305 [Security/Core] Add "is_granted()" to security expressions, deprecate "has_role()" (nicolas-grekas)
* feature #27069 [LDAP] Add "applyOperations" method to EntryManager (mablae)
* feature #27118 [BrowserKit] Adds support for meta refresh (jhedstrom)
* feature #27268 [DI] fine tune dumped factories (nicolas-grekas)
* feature #27075 [DI][DX] Allow exclude to be an array of patterns (magnetik)
* feature #27138 [HttpKernel] Better exception page when the controller returns nothing (lyrixx)

View File

@ -0,0 +1,83 @@
Code of Conduct
===============
Our Pledge
----------
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnic origin, gender identity and expression, level of
experience, education, socio-economic status, nationality, personal appearance,
religion, or sexual identity and orientation.
Our Standards
-------------
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
Our Responsibilities
--------------------
[CoC Active Response Ensurers, or CARE][1], are responsible for clarifying the
standards of acceptable behavior and are expected to take appropriate and fair
corrective action in response to any instances of unacceptable behavior.
CARE team members have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, or to ban temporarily or permanently any
contributor for other behaviors that they deem inappropriate, threatening,
offensive, or harmful.
Scope
-----
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by CARE team members.
Enforcement
-----------
Instances of abusive, harassing, or otherwise unacceptable behavior
[may be reported][2] by contacting the [CARE team members][1].
All complaints will be reviewed and investigated and will result in a response
that is deemed necessary and appropriate to the circumstances. The CARE team is
obligated to maintain confidentiality with regard to the reporter of an
incident. Further details of specific enforcement policies may be posted
separately.
CARE team members who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by the
[core team][3].
Attribution
-----------
This Code of Conduct is adapted from the [Contributor Covenant version 1.4][4].
[1]: https://symfony.com/doc/current/contributing/code_of_conduct/care_team.html
[2]: https://symfony.com/doc/current/contributing/code_of_conduct/reporting_guidelines.html
[3]: https://symfony.com/doc/current/contributing/code/core_team.html
[4]: https://www.contributor-covenant.org/version/1/4/code-of-conduct.html

View File

@ -0,0 +1,26 @@
Contributing
------------
Symfony is an open source, community-driven project.
If you'd like to contribute, please read the following documents:
* [Reviewing issues/pull requests][0]
* [Reporting a Bug][1]
* [Submitting a Patch][2]
* [Symfony Core Team][3]
* [Security Issues][4]
* [Running Symfony Tests][5]
* [Our Backwards Compatibility Promise][6]
* [Coding Standards][7]
* [Conventions][8]
[0]: https://symfony.com/doc/current/contributing/community/reviews.html
[1]: https://symfony.com/doc/current/contributing/code/bugs.html
[2]: https://symfony.com/doc/current/contributing/code/patches.html
[3]: https://symfony.com/doc/current/contributing/code/core_team.html
[4]: https://symfony.com/doc/current/contributing/code/security.html
[5]: https://symfony.com/doc/current/contributing/code/tests.html
[6]: https://symfony.com/doc/current/contributing/code/bc.html
[7]: https://symfony.com/doc/current/contributing/code/standards.html
[8]: https://symfony.com/doc/current/contributing/code/conventions.html

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,19 @@
Copyright (c) 2004-2019 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -0,0 +1,76 @@
<p align="center"><a href="https://symfony.com" target="_blank">
<img src="https://symfony.com/logos/symfony_black_02.svg">
</a></p>
[Symfony][1] is a **PHP framework** for web applications and a set of reusable
**PHP components**. Symfony is used by thousands of web applications (including
BlaBlaCar.com and Spotify.com) and most of the [popular PHP projects][2] (including
Drupal and Magento).
Installation
------------
* [Install Symfony][4] with Composer (see [requirements details][3]).
* Symfony follows the [semantic versioning][5] strictly, publishes "Long Term
Support" (LTS) versions and has a [release process][6] that is predictable and
business-friendly.
Documentation
-------------
* Read the [Getting Started guide][7] if you are new to Symfony.
* Try the [Symfony Demo application][23] to learn Symfony in practice.
* Master Symfony with the [Guides and Tutorials][8], the [Components docs][9]
and the [Best Practices][10] reference.
Community
---------
* [Join the Symfony Community][11] and meet other members at the [Symfony events][12].
* [Get Symfony support][13] on Stack Overflow, Slack, IRC, etc.
* Follow us on [GitHub][14], [Twitter][15] and [Facebook][16].
* Read our [Code of Conduct][24] and meet the [CARE Team][25]
Contributing
------------
Symfony is an Open Source, community-driven project with thousands of
[contributors][19]. Join them [contributing code][17] or [contributing documentation][18].
Security Issues
---------------
If you discover a security vulnerability within Symfony, please follow our
[disclosure procedure][20].
About Us
--------
Symfony development is sponsored by [SensioLabs][21], led by the
[Symfony Core Team][22] and supported by [Symfony contributors][19].
[1]: https://symfony.com
[2]: https://symfony.com/projects
[3]: https://symfony.com/doc/current/reference/requirements.html
[4]: https://symfony.com/doc/current/setup.html
[5]: http://semver.org
[6]: https://symfony.com/doc/current/contributing/community/releases.html
[7]: https://symfony.com/doc/current/page_creation.html
[8]: https://symfony.com/doc/current/index.html
[9]: https://symfony.com/doc/current/components/index.html
[10]: https://symfony.com/doc/current/best_practices/index.html
[11]: https://symfony.com/community
[12]: https://symfony.com/events/
[13]: https://symfony.com/support
[14]: https://github.com/symfony
[15]: https://twitter.com/symfony
[16]: https://www.facebook.com/SymfonyFramework/
[17]: https://symfony.com/doc/current/contributing/code/index.html
[18]: https://symfony.com/doc/current/contributing/documentation/index.html
[19]: https://symfony.com/contributors
[20]: https://symfony.com/security
[21]: https://sensiolabs.com
[22]: https://symfony.com/doc/current/contributing/code/core_team.html
[23]: https://github.com/symfony/symfony-demo
[24]: https://symfony.com/coc
[25]: https://symfony.com/doc/current/contributing/code_of_conduct/care_team.html

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,164 @@
UPGRADE FROM 4.0 to 4.1
=======================
Config
------
* Implementing `ParentNodeDefinitionInterface` without the `getChildNodeDefinitions()` method
is deprecated.
Console
-------
* Deprecated the `setCrossingChar()` method in favor of the `setDefaultCrossingChar()` method in `TableStyle`.
* The `Processor` class has been made final
* Deprecated the `setHorizontalBorderChar()` method in favor of the `setDefaultCrossingChars()` method in `TableStyle`.
* Deprecated the `getHorizontalBorderChar()` method in favor of the `getBorderChars()` method in `TableStyle`.
* Deprecated the `setVerticalBorderChar()` method in favor of the `setVerticalBorderChars()` method in `TableStyle`.
* Deprecated the `getVerticalBorderChar()` method in favor of the `getBorderChars()` method in `TableStyle`.
* Added support for `iterable` messages in `write` and `writeln` methods of `Symfony\Component\Console\Output\OutputInterface`.
If you have a custom implementation of the interface, you should make sure it works with iterable as well.
DependencyInjection
-------------------
* Deprecated the `TypedReference::canBeAutoregistered()` and `TypedReference::getRequiringClass()` methods.
* Deprecated support for auto-discovered extension configuration class which does not implement `ConfigurationInterface`.
EventDispatcher
---------------
* The `TraceableEventDispatcherInterface` has been deprecated.
Form
----
* Deprecated the `ChoiceLoaderInterface` implementation in `CountryType`,
`LanguageType`, `LocaleType` and `CurrencyType`, use the `choice_loader`
option instead.
Before:
```php
class MyCountryType extends CountryType
{
public function loadChoiceList()
{
// override the method
}
}
```
After:
```php
class MyCountryType extends AbstractType
{
public function getParent()
{
return CountryType::class;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefault('choice_loader', ...); // override the option instead
}
}
```
* Added `help` option to the form field. If you have custom Form extension for it, you should remove it.
Also remove it from the custom form theme.
FrameworkBundle
---------------
* Deprecated `bundle:controller:action` and `service:action` syntaxes to reference controllers. Use `serviceOrFqcn::method`
instead where `serviceOrFqcn` is either the service ID when using controllers as services or the FQCN of the controller.
Before:
```yml
bundle_controller:
path: /
defaults:
_controller: FrameworkBundle:Redirect:redirect
service_controller:
path: /
defaults:
_controller: app.my_controller:myAction
```
After:
```yml
bundle_controller:
path: /
defaults:
_controller: Symfony\Bundle\FrameworkBundle\Controller\RedirectController::redirectAction
service_controller:
path: /
defaults:
_controller: app.my_controller::myAction
```
* Deprecated `Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser`
* Warming up a router in `RouterCacheWarmer` that does not implement the `WarmableInterface` is deprecated and will not be
supported anymore in 5.0.
* The `RequestDataCollector` class has been deprecated. Use the `Symfony\Component\HttpKernel\DataCollector\RequestDataCollector` class instead.
HttpFoundation
--------------
* Passing the file size to the constructor of the `UploadedFile` class is deprecated.
* The `getClientSize()` method of the `UploadedFile` class is deprecated. Use `getSize()` instead.
* Deprecated `Symfony\Component\HttpFoundation\Request::getSession()` when no session has been set. Use `Symfony\Component\HttpFoundation\Request::hasSession()` instead.
Security
--------
* The `ContextListener::setLogoutOnUserChange()` method is deprecated.
* Using the `AdvancedUserInterface` is now deprecated. To use the existing
functionality, create a custom user-checker based on the
`Symfony\Component\Security\Core\User\UserChecker`.
* `AuthenticationUtils::getLastUsername()` now always returns a string.
* The `ExpressionVoter::addExpressionLanguageProvider()` method is deprecated. Register the provider directly on the injected ExpressionLanguage instance instead.
SecurityBundle
--------------
* The `logout_on_user_change` firewall option is deprecated.
* The `switch_user.stateless` firewall option is deprecated, use the `stateless` option instead.
* The `SecurityUserValueResolver` class is deprecated, use
`Symfony\Component\Security\Http\Controller\UserValueResolver` instead.
Serializer
----------
* Decoding XML with `XmlEncoder` now ignores comment node types by default.
Translation
-----------
* The `FileDumper::setBackup()` method is deprecated.
* The `TranslationWriter::disableBackup()` method is deprecated.
TwigBundle
----------
* Deprecated relying on the default value (`false`) of the `twig.strict_variables` configuration option. You should use `%kernel.debug%` explicitly instead, which will be the new default in 5.0.
Validator
--------
* The `Email::__construct()` 'strict' property is deprecated. Use 'mode'=>"strict" instead.
* Calling `EmailValidator::__construct()` method with a boolean parameter is deprecated, use `EmailValidator("strict")` instead.
* Deprecated the `checkDNS` and `dnsMessage` options of the `Url` constraint.
Workflow
--------
* Deprecated the `DefinitionBuilder::reset()` method, use the `clear()` one instead.
* Deprecated the `add` method in favor of the `addWorkflow` method in `Workflow\Registry`.
* Deprecated `SupportStrategyInterface` in favor of `WorkflowSupportStrategyInterface`.
* Deprecated the class `ClassInstanceSupportStrategy` in favor of the class `InstanceOfSupportStrategy`.
* Deprecated passing the workflow name as 4th parameter of `Event` constructor in favor of the workflow itself.

View File

@ -0,0 +1,392 @@
UPGRADE FROM 4.1 to 4.2
=======================
BrowserKit
----------
* The `Client::submit()` method will have a new `$serverParameters` argument in version 5.0, not defining it is deprecated.
Cache
-----
* Deprecated `CacheItem::getPreviousTags()`, use `CacheItem::getMetadata()` instead.
Config
------
* Deprecated constructing a `TreeBuilder` without passing root node information:
Before:
```php
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('my_config');
```
After:
```php
$treeBuilder = new TreeBuilder('my_config');
$rootNode = $treeBuilder->getRootNode();
```
* Deprecated `FileLoaderLoadException`, use `LoaderLoadException` instead.
Console
-------
* Deprecated passing a command as a string to `ProcessHelper::run()`,
pass the command as an array of arguments instead.
Before:
```php
$processHelper->run($output, 'ls -l');
```
After:
```php
$processHelper->run($output, array('ls', '-l'));
// alternatively, when a shell wrapper is required
$processHelper->run($output, Process::fromShellCommandline('ls -l'));
```
DoctrineBridge
--------------
* The `lazy` attribute on `doctrine.event_listener` tags was removed.
Listeners are now lazy by default. So any `lazy` attributes can safely be removed from those tags.
DomCrawler
----------
* The `Crawler::children()` method will have a new `$selector` argument in version 5.0, not defining it is deprecated.
Finder
------
* The `Finder::sortByName()` method will have a new `$useNaturalSort` argument in version 5.0, not defining it is deprecated.
Form
----
* The `symfony/translation` dependency has been removed - run `composer require symfony/translation` if you need the component
* The `getExtendedType()` method of the `FormTypeExtensionInterface` is deprecated and will be removed in 5.0. Type
extensions must implement the static `getExtendedTypes()` method instead and return an iterable of extended types.
Before:
```php
class FooTypeExtension extends AbstractTypeExtension
{
public function getExtendedType()
{
return FormType::class;
}
// ...
}
```
After:
```php
class FooTypeExtension extends AbstractTypeExtension
{
public static function getExtendedTypes(): iterable
{
return array(FormType::class);
}
// ...
}
```
* The `scale` option of the `IntegerType` is deprecated.
* The `$scale` argument of the `IntegerToLocalizedStringTransformer` is deprecated.
* Deprecated calling `FormRenderer::searchAndRenderBlock` for fields which were already rendered.
Instead of expecting such calls to return empty strings, check if the field has already been rendered.
Before:
```twig
{% for field in fieldsWithPotentialDuplicates %}
{{ form_widget(field) }}
{% endfor %}
```
After:
```twig
{% for field in fieldsWithPotentialDuplicates if not field.rendered %}
{{ form_widget(field) }}
{% endfor %}
```
* The `regions` option of the `TimezoneType` is deprecated.
FrameworkBundle
---------------
* The following middleware service ids were renamed:
- `messenger.middleware.call_message_handler` becomes `messenger.middleware.handle_message`
- `messenger.middleware.route_messages` becomes `messenger.middleware.send_message`
If you set `framework.messenger.buses.[bus_id].default_middleware` to `false`,
replace any of these names in the `framework.messenger.buses.[bus_id].middleware` list.
* The `allow_no_handler` middleware has been removed. Use `framework.messenger.buses.[bus_id].default_middleware` instead:
Before:
```yaml
framework:
messenger:
buses:
messenger.bus.events:
middleware:
- allow_no_handler
```
After:
```yaml
framework:
messenger:
buses:
messenger.bus.events:
default_middleware: allow_no_handlers
```
* The `messenger:consume-messages` command expects a mandatory `--bus` option value if you have more than one bus configured.
* The `framework.router.utf8` configuration option has been added. If your app's charset
is UTF-8 (see kernel's `getCharset()` method), it is recommended to set it to `true`:
this will generate 404s for non-UTF-8 URLs, which are incompatible with you app anyway,
and will allow dumping optimized routers and using Unicode classes in requirements.
* Added support for the SameSite attribute for session cookies. It is highly recommended to set this setting (`framework.session.cookie_samesite`) to `lax` for increased security against CSRF attacks.
* The `Controller` class has been deprecated, use `AbstractController` instead.
* The Messenger encoder/decoder configuration has been changed for a unified Messenger serializer configuration.
Before:
```yaml
framework:
messenger:
encoder: your_encoder_service_id
decoder: your_decoder_service_id
```
After:
```yaml
framework:
messenger:
serializer:
id: your_messenger_service_id
```
* The `ContainerAwareCommand` class has been deprecated, use `Symfony\Component\Console\Command\Command`
with dependency injection instead.
* The `Templating\Helper\TranslatorHelper::transChoice()` method has been deprecated, use the `trans()` one instead with a `%count%` parameter.
* Deprecated support for legacy translations directories `src/Resources/translations/` and `src/Resources/<BundleName>/translations/`, use `translations/` instead.
* Support for the legacy directory structure in `translation:update` and `debug:translation` commands has been deprecated.
HttpFoundation
--------------
* The default value of the `$secure` and `$samesite` arguments of Cookie's constructor
will respectively change from `false` to `null` and from `null` to `lax` in Symfony
5.0, you should define their values explicitly or use `Cookie::create()` instead.
HttpKernel
----------
* The `Kernel::getRootDir()` and the `kernel.root_dir` parameter have been deprecated
* The `KernelInterface::getName()` and the `kernel.name` parameter have been deprecated
* Deprecated the first and second constructor argument of `ConfigDataCollector`
* Deprecated `ConfigDataCollector::getApplicationName()`
* Deprecated `ConfigDataCollector::getApplicationVersion()`
Messenger
---------
* The `MiddlewareInterface::handle()` and `SenderInterface::send()` methods must now return an `Envelope` instance.
* The return value of handlers isn't forwarded anymore by middleware and buses.
If you used to return a value, e.g in query bus handlers, you can either:
- get the result from the `HandledStamp` in the envelope returned by the bus.
- use the `HandleTrait` to leverage a message bus, expecting a single, synchronous message handling and returning its result.
- make your `Query` mutable to allow setting & getting a result:
```php
// When dispatching:
$bus->dispatch($query = new Query());
$result = $query->getResult();
// In your handler:
$query->setResult($yourResult);
```
* The `EnvelopeAwareInterface` was removed and the `MiddlewareInterface::handle()` method now requires an `Envelope` object
as first argument. When using built-in middleware with the provided `MessageBus`, you will not have to do anything.
If you use your own `MessageBusInterface` implementation, you must wrap the message in an `Envelope` before passing it to middleware.
If you created your own middleware, you must change the signature to always expect an `Envelope`.
* The `MiddlewareInterface::handle()` second argument (`callable $next`) has changed in favor of a `StackInterface` instance.
When using built-in middleware with the provided `MessageBus`, you will not have to do anything.
If you use your own `MessageBusInterface` implementation, you can use the `StackMiddleware` implementation.
If you created your own middleware, you must change the signature to always expect an `StackInterface` instance
and call `$stack->next()->handle($envelope, $stack)` instead of `$next` to call the next middleware:
Before:
```php
public function handle($message, callable $next): Envelope
{
// do something before
$message = $next($message);
// do something after
return $message;
}
```
After:
```php
public function handle(Envelope $envelope, StackInterface $stack): Envelope
{
// do something before
$envelope = $stack->next()->handle($envelope, $stack);
// do something after
return $envelope;
}
```
* `StampInterface` replaces `EnvelopeItemInterface` and doesn't extend `Serializable` anymore.
Built-in `ReceivedMessage`, `ValidationConfiguration` and `SerializerConfiguration` were renamed
respectively `ReceivedStamp`, `ValidationStamp`, `SerializerStamp` and moved to the `Stamp` namespace.
* `AllowNoHandlerMiddleware` has been removed in favor of a new constructor argument on `HandleMessageMiddleware`
* The `ConsumeMessagesCommand` class now takes an instance of `Psr\Container\ContainerInterface`
as first constructor argument, i.e a message bus locator. The CLI command now expects a mandatory
`--bus` option value if there is more than one bus in the locator.
* `MessageSubscriberInterface::getHandledMessages()` return value has changed. The value of an array item
needs to be an associative array or the method name.
Before:
```php
return [
[FirstMessage::class, 0],
[SecondMessage::class, -10],
];
```
After:
```php
yield FirstMessage::class => ['priority' => 0];
yield SecondMessage::class => ['priority' => -10];
```
Before:
```php
return [
SecondMessage::class => ['secondMessageMethod', 20],
];
```
After:
```php
yield SecondMessage::class => [
'method' => 'secondMessageMethod',
'priority' => 20,
];
```
* The `EncoderInterface` and `DecoderInterface` interfaces have been replaced by a unified `Symfony\Component\Messenger\Transport\Serialization\SerializerInterface`.
Each interface method have been merged untouched into the `Serializer` interface, so you can simply merge your two implementations together and implement the new interface.
* The `HandlerLocator` class was replaced with `Symfony\Component\Messenger\Handler\HandlersLocator`.
Before:
```php
new HandlerLocator([
YourMessage::class => $handlerCallable,
]);
```
After:
```php
new HandlersLocator([
YourMessage::class => [
$handlerCallable,
]
]);
```
Monolog
-------
* The methods `DebugProcessor::getLogs()`, `DebugProcessor::countErrors()`, `Logger::getLogs()` and `Logger::countErrors()` will have a new `$request` argument in version 5.0, not defining it is deprecated.
Process
-------
* Deprecated the `Process::setCommandline()` and the `PhpProcess::setPhpBinary()` methods.
* Deprecated passing commands as strings when creating a `Process` instance.
Before:
```php
$process = new Process('ls -l');
```
After:
```php
$process = new Process(array('ls', '-l'));
// alternatively, when a shell wrapper is required
$process = Process::fromShellCommandline('ls -l');
```
Security
--------
* Using the `has_role()` function in security expressions is deprecated, use the `is_granted()` function instead.
* Not returning an array of 3 elements from `FirewallMapInterface::getListeners()` is deprecated, the 3rd element
must be an instance of `LogoutListener` or `null`.
* Passing custom class names to the
`Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver` to define
custom anonymous and remember me token classes is deprecated. To
use custom tokens, extend the existing `Symfony\Component\Security\Core\Authentication\Token\AnonymousToken`
or `Symfony\Component\Security\Core\Authentication\Token\RememberMeToken`.
* Accessing the user object that is not an instance of `UserInterface` from `Security::getUser()` is deprecated.
* `SimpleAuthenticatorInterface`, `SimpleFormAuthenticatorInterface`, `SimplePreAuthenticatorInterface`,
`SimpleAuthenticationProvider`, `SimpleAuthenticationHandler`, `SimpleFormAuthenticationListener` and
`SimplePreAuthenticationListener` have been deprecated. Use Guard instead.
SecurityBundle
--------------
* Passing a `FirewallConfig` instance as 3rd argument to the `FirewallContext` constructor is deprecated,
pass a `LogoutListener` instance instead.
* Using the `security.authentication.trust_resolver.anonymous_class` and
`security.authentication.trust_resolver.rememberme_class` parameters to define
the token classes is deprecated. To use
custom tokens extend the existing AnonymousToken and RememberMeToken.
* The `simple_form` and `simple_preauth` authentication listeners have been deprecated,
use Guard instead.
* The `SimpleFormFactory` and `SimplePreAuthenticationFactory` classes have been deprecated,
use Guard instead.
Serializer
----------
* Relying on the default value (false) of the "as_collection" option is deprecated.
You should set it to false explicitly instead as true will be the default value in 5.0.
* The `AbstractNormalizer::handleCircularReference()` method will have two new `$format` and `$context` arguments in version 5.0, not defining them is deprecated.
Translation
-----------
* The `TranslatorInterface` has been deprecated in favor of `Symfony\Contracts\Translation\TranslatorInterface`
* The `Translator::transChoice()` method has been deprecated in favor of using `Translator::trans()` with "%count%" as the parameter driving plurals
* The `MessageSelector`, `Interval` and `PluralizationRules` classes have been deprecated, use `IdentityTranslator` instead
* The `Translator::getFallbackLocales()` and `TranslationDataCollector::getFallbackLocales()` method have been marked as internal
TwigBundle
----------
* The `transchoice` tag and filter have been deprecated, use the `trans` ones instead with a `%count%` parameter.
* Deprecated support for legacy templates directories `src/Resources/views/` and `src/Resources/<BundleName>/views/`, use `templates/` and `templates/bundles/<BundleName>/` instead.
Validator
---------
* The `symfony/translation` dependency has been removed - run `composer require symfony/translation` if you need the component
* The `checkMX` and `checkHost` options of the `Email` constraint are deprecated
* The component is now decoupled from `symfony/translation` and uses `Symfony\Contracts\Translation\TranslatorInterface` instead
* The `ValidatorBuilderInterface` has been deprecated and `ValidatorBuilder` made final
* Deprecated validating instances of `\DateTimeInterface` in `DateTimeValidator`, `DateValidator` and `TimeValidator`. Use `Type` instead or remove the constraint if the underlying model is type hinted to `\DateTimeInterface` already.
* Using the `Bic`, `Country`, `Currency`, `Language` and `Locale` constraints without `symfony/intl` is deprecated
* Using the `Email` constraint in strict mode without `egulias/email-validator` is deprecated
* Using the `Expression` constraint without `symfony/expression-language` is deprecated

View File

@ -0,0 +1,274 @@
UPGRADE FROM 4.x to 5.0
=======================
BrowserKit
----------
* The `Client::submit()` method has a new `$serverParameters` argument.
Cache
-----
* Removed `CacheItem::getPreviousTags()`, use `CacheItem::getMetadata()` instead.
Config
------
* Dropped support for constructing a `TreeBuilder` without passing root node information.
* Added the `getChildNodeDefinitions()` method to `ParentNodeDefinitionInterface`.
* The `Processor` class has been made final
* Removed `FileLoaderLoadException`, use `LoaderLoadException` instead.
Console
-------
* Removed the `setCrossingChar()` method in favor of the `setDefaultCrossingChar()` method in `TableStyle`.
* Removed the `setHorizontalBorderChar()` method in favor of the `setDefaultCrossingChars()` method in `TableStyle`.
* Removed the `getHorizontalBorderChar()` method in favor of the `getBorderChars()` method in `TableStyle`.
* Removed the `setVerticalBorderChar()` method in favor of the `setVerticalBorderChars()` method in `TableStyle`.
* Removed the `getVerticalBorderChar()` method in favor of the `getBorderChars()` method in `TableStyle`.
* The `ProcessHelper::run()` method takes the command as an array of arguments.
Before:
```php
$processHelper->run($output, 'ls -l');
```
After:
```php
$processHelper->run($output, array('ls', '-l'));
// alternatively, when a shell wrapper is required
$processHelper->run($output, Process::fromShellCommandline('ls -l'));
```
DependencyInjection
-------------------
* Removed the `TypedReference::canBeAutoregistered()` and `TypedReference::getRequiringClass()` methods.
* Removed support for auto-discovered extension configuration class which does not implement `ConfigurationInterface`.
DoctrineBridge
--------------
* Deprecated injecting `ClassMetadataFactory` in `DoctrineExtractor`, an instance of `EntityManagerInterface` should be
injected instead
DomCrawler
----------
* The `Crawler::children()` method has a new `$selector` argument.
EventDispatcher
---------------
* The `TraceableEventDispatcherInterface` has been removed.
Finder
------
* The `Finder::sortByName()` method has a new `$useNaturalSort` argument.
Form
----
* The `getExtendedType()` method was removed from the `FormTypeExtensionInterface`. It is replaced by the the static
`getExtendedTypes()` method which must return an iterable of extended types.
Before:
```php
class FooTypeExtension extends AbstractTypeExtension
{
public function getExtendedType()
{
return FormType::class;
}
// ...
}
```
After:
```php
class FooTypeExtension extends AbstractTypeExtension
{
public static function getExtendedTypes(): iterable
{
return array(FormType::class);
}
// ...
}
```
* The `scale` option was removed from the `IntegerType`.
* The `$scale` argument of the `IntegerToLocalizedStringTransformer` was removed.
* Calling `FormRenderer::searchAndRenderBlock` for fields which were already rendered
throws an exception instead of returning empty strings:
Before:
```twig
{% for field in fieldsWithPotentialDuplicates %}
{{ form_widget(field) }}
{% endfor %}
```
After:
```twig
{% for field in fieldsWithPotentialDuplicates if not field.rendered %}
{{ form_widget(field) }}
{% endfor %}
```
* The `regions` option was removed from the `TimezoneType`.
FrameworkBundle
---------------
* Removed support for `bundle:controller:action` syntax to reference controllers. Use `serviceOrFqcn::method`
instead where `serviceOrFqcn` is either the service ID when using controllers as services or the FQCN of the controller.
Before:
```yml
bundle_controller:
path: /
defaults:
_controller: FrameworkBundle:Redirect:redirect
```
After:
```yml
bundle_controller:
path: /
defaults:
_controller: Symfony\Bundle\FrameworkBundle\Controller\RedirectController::redirectAction
```
* Removed `Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser`.
* Warming up a router in `RouterCacheWarmer` that does not implement the `WarmableInterface` is not supported anymore.
* The `RequestDataCollector` class has been removed. Use the `Symfony\Component\HttpKernel\DataCollector\RequestDataCollector` class instead.
* Removed `Symfony\Bundle\FrameworkBundle\Controller\Controller`. Use `Symfony\Bundle\FrameworkBundle\Controller\AbstractController` instead.
* Added support for the SameSite attribute for session cookies. It is highly recommended to set this setting (`framework.session.cookie_samesite`) to `lax` for increased security against CSRF attacks.
* The `ContainerAwareCommand` class has been removed, use `Symfony\Component\Console\Command\Command`
with dependency injection instead.
* The `Templating\Helper\TranslatorHelper::transChoice()` method has been removed, use the `trans()` one instead with a `%count%` parameter.
* Removed support for legacy translations directories `src/Resources/translations/` and `src/Resources/<BundleName>/translations/`, use `translations/` instead.
* Support for the legacy directory structure in `translation:update` and `debug:translation` commands has been removed.
HttpFoundation
--------------
* The `$size` argument of the `UploadedFile` constructor has been removed.
* The `getClientSize()` method of the `UploadedFile` class has been removed.
* The `getSession()` method of the `Request` class throws an exception when session is null.
* The default value of the "$secure" and "$samesite" arguments of Cookie's constructor
changed respectively from "false" to "null" and from "null" to "lax".
HttpKernel
----------
* The `Kernel::getRootDir()` and the `kernel.root_dir` parameter have been removed
* The `KernelInterface::getName()` and the `kernel.name` parameter have been removed
* Removed the first and second constructor argument of `ConfigDataCollector`
* Removed `ConfigDataCollector::getApplicationName()`
* Removed `ConfigDataCollector::getApplicationVersion()`
Monolog
-------
* The methods `DebugProcessor::getLogs()`, `DebugProcessor::countErrors()`, `Logger::getLogs()` and `Logger::countErrors()` have a new `$request` argument.
Process
-------
* Removed the `Process::setCommandline()` and the `PhpProcess::setPhpBinary()` methods.
* Commands must be defined as arrays when creating a `Process` instance.
Before:
```php
$process = new Process('ls -l');
```
After:
```php
$process = new Process(array('ls', '-l'));
// alternatively, when a shell wrapper is required
$process = Process::fromShellCommandline('ls -l');
```
Security
--------
* The `ContextListener::setLogoutOnUserChange()` method has been removed.
* The `Symfony\Component\Security\Core\User\AdvancedUserInterface` has been removed.
* The `ExpressionVoter::addExpressionLanguageProvider()` method has been removed.
* The `FirewallMapInterface::getListeners()` method must return an array of 3 elements,
the 3rd one must be either a `LogoutListener` instance or `null`.
* The `AuthenticationTrustResolver` constructor arguments have been removed.
* A user object that is not an instance of `UserInterface` cannot be accessed from `Security::getUser()` anymore and returns `null` instead.
* `SimpleAuthenticatorInterface`, `SimpleFormAuthenticatorInterface`, `SimplePreAuthenticatorInterface`,
`SimpleAuthenticationProvider`, `SimpleAuthenticationHandler`, `SimpleFormAuthenticationListener` and
`SimplePreAuthenticationListener` have been removed. Use Guard instead.
SecurityBundle
--------------
* The `logout_on_user_change` firewall option has been removed.
* The `switch_user.stateless` firewall option has been removed.
* The `SecurityUserValueResolver` class has been removed.
* Passing a `FirewallConfig` instance as 3rd argument to the `FirewallContext` constructor
now throws a `\TypeError`, pass a `LogoutListener` instance instead.
* The `security.authentication.trust_resolver.anonymous_class` parameter has been removed.
* The `security.authentication.trust_resolver.rememberme_class` parameter has been removed.
* The `simple_form` and `simple_preauth` authentication listeners have been removed,
use Guard instead.
* The `SimpleFormFactory` and `SimplePreAuthenticationFactory` classes have been removed,
use Guard instead.
Serializer
----------
* The `AbstractNormalizer::handleCircularReference()` method has two new `$format` and `$context` arguments.
Translation
-----------
* The `FileDumper::setBackup()` method has been removed.
* The `TranslationWriter::disableBackup()` method has been removed.
* The `TranslatorInterface` has been removed in favor of `Symfony\Contracts\Translation\TranslatorInterface`
* The `MessageSelector`, `Interval` and `PluralizationRules` classes have been removed, use `IdentityTranslator` instead
* The `Translator::getFallbackLocales()` and `TranslationDataCollector::getFallbackLocales()` method are now internal
* The `Translator::transChoice()` method has been removed in favor of using `Translator::trans()` with "%count%" as the parameter driving plurals
TwigBundle
----------
* The default value (`false`) of the `twig.strict_variables` configuration option has been changed to `%kernel.debug%`.
* The `transchoice` tag and filter have been removed, use the `trans` ones instead with a `%count%` parameter.
* Removed support for legacy templates directories `src/Resources/views/` and `src/Resources/<BundleName>/views/`, use `templates/` and `templates/bundles/<BundleName>/` instead.
Validator
--------
* The `checkMX` and `checkHost` options of the `Email` constraint were removed
* The `Email::__construct()` 'strict' property has been removed. Use 'mode'=>"strict" instead.
* Calling `EmailValidator::__construct()` method with a boolean parameter has been removed, use `EmailValidator("strict")` instead.
* Removed the `checkDNS` and `dnsMessage` options from the `Url` constraint.
* The component is now decoupled from `symfony/translation` and uses `Symfony\Contracts\Translation\TranslatorInterface` instead
* The `ValidatorBuilderInterface` has been removed and `ValidatorBuilder` is now final
* Removed support for validating instances of `\DateTimeInterface` in `DateTimeValidator`, `DateValidator` and `TimeValidator`. Use `Type` instead or remove the constraint if the underlying model is type hinted to `\DateTimeInterface` already.
* The `symfony/intl` component is now required for using the `Bic`, `Country`, `Currency`, `Language` and `Locale` constraints
* The `egulias/email-validator` component is now required for using the `Email` constraint in strict mode
* The `symfony/expression-language` component is now required for using the `Expression` constraint
Workflow
--------
* The `DefinitionBuilder::reset()` method has been removed, use the `clear()` one instead.
* `add` method has been removed use `addWorkflow` method in `Workflow\Registry` instead.
* `SupportStrategyInterface` has been removed, use `WorkflowSupportStrategyInterface` instead.
* `ClassInstanceSupportStrategy` has been removed, use `InstanceOfSupportStrategy` instead.

View File

@ -0,0 +1,153 @@
{
"name": "symfony/symfony",
"type": "library",
"description": "The Symfony PHP framework",
"keywords": ["framework"],
"homepage": "https://symfony.com",
"license": "MIT",
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"require": {
"php": "^7.1.3",
"ext-xml": "*",
"doctrine/collections": "~1.0",
"doctrine/event-manager": "~1.0",
"doctrine/persistence": "~1.0",
"fig/link-util": "^1.0",
"twig/twig": "^1.40|^2.9",
"psr/cache": "~1.0",
"psr/container": "^1.0",
"psr/link": "^1.0",
"psr/log": "~1.0",
"psr/simple-cache": "^1.0",
"symfony/contracts": "^1.0.2",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-intl-icu": "~1.0",
"symfony/polyfill-mbstring": "~1.0",
"symfony/polyfill-php72": "~1.5"
},
"replace": {
"symfony/asset": "self.version",
"symfony/browser-kit": "self.version",
"symfony/cache": "self.version",
"symfony/config": "self.version",
"symfony/console": "self.version",
"symfony/css-selector": "self.version",
"symfony/dependency-injection": "self.version",
"symfony/debug": "self.version",
"symfony/debug-bundle": "self.version",
"symfony/doctrine-bridge": "self.version",
"symfony/dom-crawler": "self.version",
"symfony/dotenv": "self.version",
"symfony/event-dispatcher": "self.version",
"symfony/expression-language": "self.version",
"symfony/filesystem": "self.version",
"symfony/finder": "self.version",
"symfony/form": "self.version",
"symfony/framework-bundle": "self.version",
"symfony/http-foundation": "self.version",
"symfony/http-kernel": "self.version",
"symfony/inflector": "self.version",
"symfony/intl": "self.version",
"symfony/ldap": "self.version",
"symfony/lock": "self.version",
"symfony/messenger": "self.version",
"symfony/monolog-bridge": "self.version",
"symfony/options-resolver": "self.version",
"symfony/process": "self.version",
"symfony/property-access": "self.version",
"symfony/property-info": "self.version",
"symfony/proxy-manager-bridge": "self.version",
"symfony/routing": "self.version",
"symfony/security": "self.version",
"symfony/security-core": "self.version",
"symfony/security-csrf": "self.version",
"symfony/security-guard": "self.version",
"symfony/security-http": "self.version",
"symfony/security-bundle": "self.version",
"symfony/serializer": "self.version",
"symfony/stopwatch": "self.version",
"symfony/templating": "self.version",
"symfony/translation": "self.version",
"symfony/twig-bridge": "self.version",
"symfony/twig-bundle": "self.version",
"symfony/validator": "self.version",
"symfony/var-dumper": "self.version",
"symfony/var-exporter": "self.version",
"symfony/web-link": "self.version",
"symfony/web-profiler-bundle": "self.version",
"symfony/web-server-bundle": "self.version",
"symfony/workflow": "self.version",
"symfony/yaml": "self.version"
},
"require-dev": {
"cache/integration-tests": "dev-master",
"doctrine/annotations": "~1.0",
"doctrine/cache": "~1.6",
"doctrine/data-fixtures": "1.0.*",
"doctrine/dbal": "~2.4",
"doctrine/orm": "~2.4,>=2.4.5",
"doctrine/reflection": "~1.0",
"doctrine/doctrine-bundle": "~1.4",
"monolog/monolog": "~1.11",
"ocramius/proxy-manager": "~0.4|~1.0|~2.0",
"predis/predis": "~1.1",
"egulias/email-validator": "~1.2,>=1.2.8|~2.0",
"symfony/phpunit-bridge": "~3.4|~4.0",
"symfony/security-acl": "~2.8|~3.0",
"phpdocumentor/reflection-docblock": "^3.0|^4.0"
},
"conflict": {
"phpdocumentor/reflection-docblock": "<3.0||>=3.2.0,<3.2.2",
"phpdocumentor/type-resolver": "<0.3.0",
"phpunit/phpunit": "<5.4.3"
},
"provide": {
"psr/cache-implementation": "1.0",
"psr/container-implementation": "1.0",
"psr/log-implementation": "1.0",
"psr/simple-cache-implementation": "1.0",
"symfony/cache-contracts": "1.0",
"symfony/service-contracts": "1.0",
"symfony/translation-contracts": "1.0"
},
"autoload": {
"psr-4": {
"Symfony\\Bridge\\Doctrine\\": "src/Symfony/Bridge/Doctrine/",
"Symfony\\Bridge\\Monolog\\": "src/Symfony/Bridge/Monolog/",
"Symfony\\Bridge\\ProxyManager\\": "src/Symfony/Bridge/ProxyManager/",
"Symfony\\Bridge\\Twig\\": "src/Symfony/Bridge/Twig/",
"Symfony\\Bundle\\": "src/Symfony/Bundle/",
"Symfony\\Component\\": "src/Symfony/Component/"
},
"classmap": [
"src/Symfony/Component/Intl/Resources/stubs"
],
"exclude-from-classmap": [
"**/Tests/"
]
},
"autoload-dev": {
"files": [ "src/Symfony/Component/VarDumper/Resources/functions/dump.php" ]
},
"repositories": [
{
"type": "path",
"url": "src/Symfony/Contracts"
}
],
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "4.2-dev"
}
}
}

73
msd2/myoos/vendor/symfony/symfony/link vendored Normal file
View File

@ -0,0 +1,73 @@
#!/usr/bin/env php
<?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.
*/
require __DIR__.'/src/Symfony/Component/Filesystem/Exception/ExceptionInterface.php';
require __DIR__.'/src/Symfony/Component/Filesystem/Exception/IOExceptionInterface.php';
require __DIR__.'/src/Symfony/Component/Filesystem/Exception/IOException.php';
require __DIR__.'/src/Symfony/Component/Filesystem/Filesystem.php';
use Symfony\Component\Filesystem\Filesystem;
/**
* Links dependencies to components to a local clone of the main symfony/symfony GitHub repository.
*
* @author Kévin Dunglas <dunglas@gmail.com>
*/
if (2 !== $argc) {
echo 'Link dependencies to components to a local clone of the main symfony/symfony GitHub repository.'.PHP_EOL.PHP_EOL;
echo "Usage: $argv[0] /path/to/the/project".PHP_EOL;
exit(1);
}
if (!is_dir("$argv[1]/vendor/symfony")) {
echo "The directory \"$argv[1]\" does not exist or the dependencies are not installed, did you forget to run \"composer install\" in your project?".PHP_EOL;
exit(1);
}
$sfPackages = array('symfony/symfony' => __DIR__);
$filesystem = new Filesystem();
$braces = array('Bundle', 'Bridge', 'Component', 'Component/Security');
$directories = array_merge(...array_values(array_map(function ($part) {
return glob(__DIR__.'/src/Symfony/'.$part.'/*', GLOB_ONLYDIR | GLOB_NOSORT);
}, $braces)));
$directories[] = __DIR__.'/src/Symfony/Contracts';
foreach ($directories as $dir) {
if ($filesystem->exists($composer = "$dir/composer.json")) {
$sfPackages[json_decode(file_get_contents($composer))->name] = $dir;
}
}
foreach (glob("$argv[1]/vendor/symfony/*", GLOB_ONLYDIR | GLOB_NOSORT) as $dir) {
$package = 'symfony/'.basename($dir);
if (is_link($dir)) {
echo "\"$package\" is already a symlink, skipping.".PHP_EOL;
continue;
}
if (!isset($sfPackages[$package])) {
continue;
}
$sfDir = '\\' === DIRECTORY_SEPARATOR ? $sfPackages[$package] : $filesystem->makePathRelative($sfPackages[$package], dirname(realpath($dir)));
$filesystem->remove($dir);
$filesystem->symlink($sfDir, $dir);
echo "\"$package\" has been linked to \"$sfPackages[$package]\".".PHP_EOL;
}
foreach (glob("$argv[1]/var/cache/*") as $cacheDir) {
$filesystem->remove($cacheDir);
}

View File

@ -0,0 +1,14 @@
#!/usr/bin/env php
<?php
// Cache-Id: https://github.com/symfony/phpunit-bridge/commit/32c5fa570117630dad45c21528b93d26bad02bc1
if (!file_exists(__DIR__.'/vendor/symfony/phpunit-bridge/bin/simple-phpunit')) {
echo "Unable to find the `simple-phpunit` script in `vendor/symfony/phpunit-bridge/bin/`.\nPlease run `composer update` before running this command.\n";
exit(1);
}
if (\PHP_VERSION_ID >= 70000 && !getenv('SYMFONY_PHPUNIT_VERSION')) {
putenv('SYMFONY_PHPUNIT_VERSION=6.5');
}
putenv('SYMFONY_PHPUNIT_DIR='.__DIR__.'/.phpunit');
require __DIR__.'/vendor/symfony/phpunit-bridge/bin/simple-phpunit';

View File

@ -0,0 +1,82 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/5.2/phpunit.xsd"
backupGlobals="false"
colors="true"
bootstrap="vendor/autoload.php"
failOnRisky="true"
failOnWarning="true"
>
<php>
<ini name="error_reporting" value="-1" />
<ini name="intl.default_locale" value="en" />
<ini name="intl.error_level" value="0" />
<ini name="memory_limit" value="-1" />
<env name="DUMP_LIGHT_ARRAY" value="" />
<env name="DUMP_STRING_LENGTH" value="" />
<env name="LDAP_HOST" value="127.0.0.1" />
<env name="LDAP_PORT" value="3389" />
<env name="REDIS_HOST" value="localhost" />
<env name="MEMCACHED_HOST" value="localhost" />
<env name="ZOOKEEPER_HOST" value="localhost" />
</php>
<testsuites>
<testsuite name="Symfony Test Suite">
<directory>./src/Symfony/Bridge/*/Tests/</directory>
<directory>./src/Symfony/Component/*/Tests/</directory>
<directory>./src/Symfony/Component/*/*/Tests/</directory>
<directory>./src/Symfony/Contract/*/Tests/</directory>
<directory>./src/Symfony/Bundle/*/Tests/</directory>
</testsuite>
</testsuites>
<groups>
<exclude>
<group>benchmark</group>
<group>intl-data</group>
</exclude>
</groups>
<filter>
<whitelist>
<directory>./src/Symfony/</directory>
<exclude>
<directory>./src/Symfony/Bridge/*/Tests</directory>
<directory>./src/Symfony/Component/*/Tests</directory>
<directory>./src/Symfony/Component/*/*/Tests</directory>
<directory>./src/Symfony/Contract/*/Tests</directory>
<directory>./src/Symfony/Bundle/*/Tests</directory>
<directory>./src/Symfony/Bundle/*/Resources</directory>
<directory>./src/Symfony/Component/*/Resources</directory>
<directory>./src/Symfony/Component/*/*/Resources</directory>
<directory>./src/Symfony/Bridge/*/vendor</directory>
<directory>./src/Symfony/Bundle/*/vendor</directory>
<directory>./src/Symfony/Component/*/vendor</directory>
<directory>./src/Symfony/Component/*/*/vendor</directory>
<directory>./src/Symfony/Contract/*/vendor</directory>
</exclude>
</whitelist>
</filter>
<listeners>
<listener class="Symfony\Bridge\PhpUnit\SymfonyTestsListener">
<arguments>
<array>
<element key="time-sensitive">
<array>
<element key="0"><string>Cache\IntegrationTests</string></element>
<element key="1"><string>Doctrine\Common\Cache</string></element>
<element key="2"><string>Symfony\Component\Cache</string></element>
<element key="3"><string>Symfony\Component\Cache\Tests\Fixtures</string></element>
<element key="4"><string>Symfony\Component\Cache\Traits</string></element>
<element key="5"><string>Symfony\Component\Console</string></element>
<element key="6"><string>Symfony\Component\HttpFoundation</string></element>
</array>
</element>
</array>
</arguments>
</listener>
</listeners>
</phpunit>

View File

@ -0,0 +1,3 @@
vendor/
composer.lock
phpunit.xml

View File

@ -0,0 +1,89 @@
CHANGELOG
=========
4.2.0
-----
* deprecated injecting `ClassMetadataFactory` in `DoctrineExtractor`,
an instance of `EntityManagerInterface` should be injected instead
* added support for `simple_array` type
* the `DoctrineTransactionMiddlewareFactory` class has been removed
4.1.0
-----
* added support for datetime immutable types in form type guesser
4.0.0
-----
* the first constructor argument of the `DoctrineChoiceLoader` class must be
an `ObjectManager` implementation
* removed the `MergeDoctrineCollectionListener::onBind()` method
* trying to reset a non-lazy manager service using the `ManagerRegistry::resetService()`
method throws an exception
* removed the `DoctrineParserCache` class
3.4.0
-----
* added support for doctrine/dbal v2.6 types
* added cause of UniqueEntity constraint violation
* deprecated `DbalSessionHandler` and `DbalSessionHandlerSchema` in favor of
`Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler`
3.1.0
-----
* added "{{ value }}" message placeholder to UniqueEntityValidator
* deprecated `MergeDoctrineCollectionListener::onBind` in favor of
`MergeDoctrineCollectionListener::onSubmit`
* deprecated passing `ChoiceListFactoryInterface` as first argument of
`DoctrineChoiceLoader`'s constructor
3.0.0
-----
* removed `EntityChoiceList`
* removed `$manager` (2nd) and `$class` (3th) arguments of `ORMQueryBuilderLoader`
* removed passing a query builder closure to `ORMQueryBuilderLoader`
* removed `loader` and `property` options of the `DoctrineType`
2.8.0
-----
* deprecated using the entity provider with a Doctrine repository implementing UserProviderInterface
* added UserLoaderInterface for loading users through Doctrine.
2.7.0
-----
* added DoctrineChoiceLoader
* deprecated EntityChoiceList
* deprecated passing a query builder closure to ORMQueryBuilderLoader
* deprecated $manager and $em arguments of ORMQueryBuilderLoader
* added optional arguments $propertyAccessor and $choiceListFactory to DoctrineOrmExtension constructor
* deprecated "loader" and "property" options of DoctrineType
2.4.0
-----
* deprecated DoctrineOrmTestCase class
2.2.0
-----
* added an optional PropertyAccessorInterface parameter to DoctrineType,
EntityType and EntityChoiceList
2.1.0
-----
* added a default implementation of the ManagerRegistry
* added a session storage for Doctrine DBAL
* DoctrineOrmTypeGuesser now guesses "collection" for array Doctrine type
* DoctrineType now caches its choice lists in order to improve performance
* DoctrineType now uses ManagerRegistry::getManagerForClass() if the option "em" is not set
* UniqueEntity validation constraint now accepts a "repositoryMethod" option that will be used to check for uniqueness instead of the default "findBy"
* [BC BREAK] the DbalLogger::log() visibility has been changed from public to
protected

View File

@ -0,0 +1,69 @@
<?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\Doctrine\CacheWarmer;
use Doctrine\Common\Persistence\ManagerRegistry;
use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface;
/**
* The proxy generator cache warmer generates all entity proxies.
*
* In the process of generating proxies the cache for all the metadata is primed also,
* since this information is necessary to build the proxies in the first place.
*
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class ProxyCacheWarmer implements CacheWarmerInterface
{
private $registry;
public function __construct(ManagerRegistry $registry)
{
$this->registry = $registry;
}
/**
* This cache warmer is not optional, without proxies fatal error occurs!
*
* @return false
*/
public function isOptional()
{
return false;
}
/**
* {@inheritdoc}
*/
public function warmUp($cacheDir)
{
foreach ($this->registry->getManagers() as $em) {
// we need the directory no matter the proxy cache generation strategy
if (!is_dir($proxyCacheDir = $em->getConfiguration()->getProxyDir())) {
if (false === @mkdir($proxyCacheDir, 0777, true)) {
throw new \RuntimeException(sprintf('Unable to create the Doctrine Proxy directory "%s".', $proxyCacheDir));
}
} elseif (!is_writable($proxyCacheDir)) {
throw new \RuntimeException(sprintf('The Doctrine Proxy directory "%s" is not writeable for the current system user.', $proxyCacheDir));
}
// if proxies are autogenerated we don't need to generate them in the cache warmer
if ($em->getConfiguration()->getAutoGenerateProxyClasses()) {
continue;
}
$classes = $em->getMetadataFactory()->getAllMetadata();
$em->getProxyFactory()->generateProxyClasses($classes);
}
}
}

View File

@ -0,0 +1,141 @@
<?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\Doctrine;
use Doctrine\Common\EventArgs;
use Doctrine\Common\EventManager;
use Psr\Container\ContainerInterface;
/**
* Allows lazy loading of listener services.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class ContainerAwareEventManager extends EventManager
{
/**
* Map of registered listeners.
*
* <event> => <listeners>
*/
private $listeners = [];
private $initialized = [];
private $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
/**
* Dispatches an event to all registered listeners.
*
* @param string $eventName The name of the event to dispatch. The name of the event is
* the name of the method that is invoked on listeners.
* @param EventArgs $eventArgs The event arguments to pass to the event handlers/listeners.
* If not supplied, the single empty EventArgs instance is used.
*
* @return bool
*/
public function dispatchEvent($eventName, EventArgs $eventArgs = null)
{
if (isset($this->listeners[$eventName])) {
$eventArgs = null === $eventArgs ? EventArgs::getEmptyInstance() : $eventArgs;
$initialized = isset($this->initialized[$eventName]);
foreach ($this->listeners[$eventName] as $hash => $listener) {
if (!$initialized && \is_string($listener)) {
$this->listeners[$eventName][$hash] = $listener = $this->container->get($listener);
}
$listener->$eventName($eventArgs);
}
$this->initialized[$eventName] = true;
}
}
/**
* Gets the listeners of a specific event or all listeners.
*
* @param string $event The name of the event
*
* @return array The event listeners for the specified event, or all event listeners
*/
public function getListeners($event = null)
{
return $event ? $this->listeners[$event] : $this->listeners;
}
/**
* Checks whether an event has any registered listeners.
*
* @param string $event
*
* @return bool TRUE if the specified event has any listeners, FALSE otherwise
*/
public function hasListeners($event)
{
return isset($this->listeners[$event]) && $this->listeners[$event];
}
/**
* Adds an event listener that listens on the specified events.
*
* @param string|array $events The event(s) to listen on
* @param object|string $listener The listener object
*
* @throws \RuntimeException
*/
public function addEventListener($events, $listener)
{
if (\is_string($listener)) {
if ($this->initialized) {
throw new \RuntimeException('Adding lazy-loading listeners after construction is not supported.');
}
$hash = '_service_'.$listener;
} else {
// Picks the hash code related to that listener
$hash = spl_object_hash($listener);
}
foreach ((array) $events as $event) {
// Overrides listener if a previous one was associated already
// Prevents duplicate listeners on same event (same instance only)
$this->listeners[$event][$hash] = $listener;
}
}
/**
* Removes an event listener from the specified events.
*
* @param string|array $events
* @param object|string $listener
*/
public function removeEventListener($events, $listener)
{
if (\is_string($listener)) {
$hash = '_service_'.$listener;
} else {
// Picks the hash code related to that listener
$hash = spl_object_hash($listener);
}
foreach ((array) $events as $event) {
// Check if actually have this listener associated
if (isset($this->listeners[$event][$hash])) {
unset($this->listeners[$event][$hash]);
}
}
}
}

View File

@ -0,0 +1,205 @@
<?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\Doctrine\DataCollector;
use Doctrine\Common\Persistence\ManagerRegistry;
use Doctrine\DBAL\Logging\DebugStack;
use Doctrine\DBAL\Types\ConversionException;
use Doctrine\DBAL\Types\Type;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\DataCollector\DataCollector;
/**
* DoctrineDataCollector.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class DoctrineDataCollector extends DataCollector
{
private $registry;
private $connections;
private $managers;
/**
* @var DebugStack[]
*/
private $loggers = [];
public function __construct(ManagerRegistry $registry)
{
$this->registry = $registry;
$this->connections = $registry->getConnectionNames();
$this->managers = $registry->getManagerNames();
}
/**
* Adds the stack logger for a connection.
*
* @param string $name
* @param DebugStack $logger
*/
public function addLogger($name, DebugStack $logger)
{
$this->loggers[$name] = $logger;
}
/**
* {@inheritdoc}
*/
public function collect(Request $request, Response $response, \Exception $exception = null)
{
$queries = [];
foreach ($this->loggers as $name => $logger) {
$queries[$name] = $this->sanitizeQueries($name, $logger->queries);
}
$this->data = [
'queries' => $queries,
'connections' => $this->connections,
'managers' => $this->managers,
];
}
public function reset()
{
$this->data = [];
foreach ($this->loggers as $logger) {
$logger->queries = [];
$logger->currentQuery = 0;
}
}
public function getManagers()
{
return $this->data['managers'];
}
public function getConnections()
{
return $this->data['connections'];
}
public function getQueryCount()
{
return array_sum(array_map('count', $this->data['queries']));
}
public function getQueries()
{
return $this->data['queries'];
}
public function getTime()
{
$time = 0;
foreach ($this->data['queries'] as $queries) {
foreach ($queries as $query) {
$time += $query['executionMS'];
}
}
return $time;
}
/**
* {@inheritdoc}
*/
public function getName()
{
return 'db';
}
private function sanitizeQueries($connectionName, $queries)
{
foreach ($queries as $i => $query) {
$queries[$i] = $this->sanitizeQuery($connectionName, $query);
}
return $queries;
}
private function sanitizeQuery($connectionName, $query)
{
$query['explainable'] = true;
if (null === $query['params']) {
$query['params'] = [];
}
if (!\is_array($query['params'])) {
$query['params'] = [$query['params']];
}
foreach ($query['params'] as $j => $param) {
if (isset($query['types'][$j])) {
// Transform the param according to the type
$type = $query['types'][$j];
if (\is_string($type)) {
$type = Type::getType($type);
}
if ($type instanceof Type) {
$query['types'][$j] = $type->getBindingType();
try {
$param = $type->convertToDatabaseValue($param, $this->registry->getConnection($connectionName)->getDatabasePlatform());
} catch (\TypeError $e) {
// Error thrown while processing params, query is not explainable.
$query['explainable'] = false;
} catch (ConversionException $e) {
$query['explainable'] = false;
}
}
}
list($query['params'][$j], $explainable) = $this->sanitizeParam($param);
if (!$explainable) {
$query['explainable'] = false;
}
}
return $query;
}
/**
* Sanitizes a param.
*
* The return value is an array with the sanitized value and a boolean
* indicating if the original value was kept (allowing to use the sanitized
* value to explain the query).
*/
private function sanitizeParam($var): array
{
if (\is_object($var)) {
$className = \get_class($var);
return method_exists($var, '__toString') ?
[sprintf('/* Object(%s): */"%s"', $className, $var->__toString()), false] :
[sprintf('/* Object(%s) */', $className), false];
}
if (\is_array($var)) {
$a = [];
$original = true;
foreach ($var as $k => $v) {
list($value, $orig) = $this->sanitizeParam($v);
$original = $original && $orig;
$a[$k] = $value;
}
return [$a, $original];
}
if (\is_resource($var)) {
return [sprintf('/* Resource(%s) */', get_resource_type($var)), false];
}
return [$var, true];
}
}

View File

@ -0,0 +1,46 @@
<?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\Doctrine\DataFixtures;
use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\DataFixtures\Loader;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Doctrine data fixtures loader that injects the service container into
* fixture objects that implement ContainerAwareInterface.
*
* Note: Use of this class requires the Doctrine data fixtures extension, which
* is a suggested dependency for Symfony.
*/
class ContainerAwareLoader extends Loader
{
private $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
/**
* {@inheritdoc}
*/
public function addFixture(FixtureInterface $fixture)
{
if ($fixture instanceof ContainerAwareInterface) {
$fixture->setContainer($this->container);
}
parent::addFixture($fixture);
}
}

View File

@ -0,0 +1,468 @@
<?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\Doctrine\DependencyInjection;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
/**
* This abstract classes groups common code that Doctrine Object Manager extensions (ORM, MongoDB, CouchDB) need.
*
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
abstract class AbstractDoctrineExtension extends Extension
{
/**
* Used inside metadata driver method to simplify aggregation of data.
*/
protected $aliasMap = [];
/**
* Used inside metadata driver method to simplify aggregation of data.
*/
protected $drivers = [];
/**
* @param array $objectManager A configured object manager
* @param ContainerBuilder $container A ContainerBuilder instance
*
* @throws \InvalidArgumentException
*/
protected function loadMappingInformation(array $objectManager, ContainerBuilder $container)
{
if ($objectManager['auto_mapping']) {
// automatically register bundle mappings
foreach (array_keys($container->getParameter('kernel.bundles')) as $bundle) {
if (!isset($objectManager['mappings'][$bundle])) {
$objectManager['mappings'][$bundle] = [
'mapping' => true,
'is_bundle' => true,
];
}
}
}
foreach ($objectManager['mappings'] as $mappingName => $mappingConfig) {
if (null !== $mappingConfig && false === $mappingConfig['mapping']) {
continue;
}
$mappingConfig = array_replace([
'dir' => false,
'type' => false,
'prefix' => false,
], (array) $mappingConfig);
$mappingConfig['dir'] = $container->getParameterBag()->resolveValue($mappingConfig['dir']);
// a bundle configuration is detected by realizing that the specified dir is not absolute and existing
if (!isset($mappingConfig['is_bundle'])) {
$mappingConfig['is_bundle'] = !is_dir($mappingConfig['dir']);
}
if ($mappingConfig['is_bundle']) {
$bundle = null;
foreach ($container->getParameter('kernel.bundles') as $name => $class) {
if ($mappingName === $name) {
$bundle = new \ReflectionClass($class);
break;
}
}
if (null === $bundle) {
throw new \InvalidArgumentException(sprintf('Bundle "%s" does not exist or it is not enabled.', $mappingName));
}
$mappingConfig = $this->getMappingDriverBundleConfigDefaults($mappingConfig, $bundle, $container);
if (!$mappingConfig) {
continue;
}
}
$this->assertValidMappingConfiguration($mappingConfig, $objectManager['name']);
$this->setMappingDriverConfig($mappingConfig, $mappingName);
$this->setMappingDriverAlias($mappingConfig, $mappingName);
}
}
/**
* Register the alias for this mapping driver.
*
* Aliases can be used in the Query languages of all the Doctrine object managers to simplify writing tasks.
*
* @param array $mappingConfig
* @param string $mappingName
*/
protected function setMappingDriverAlias($mappingConfig, $mappingName)
{
if (isset($mappingConfig['alias'])) {
$this->aliasMap[$mappingConfig['alias']] = $mappingConfig['prefix'];
} else {
$this->aliasMap[$mappingName] = $mappingConfig['prefix'];
}
}
/**
* Register the mapping driver configuration for later use with the object managers metadata driver chain.
*
* @param array $mappingConfig
* @param string $mappingName
*
* @throws \InvalidArgumentException
*/
protected function setMappingDriverConfig(array $mappingConfig, $mappingName)
{
$mappingDirectory = $mappingConfig['dir'];
if (!is_dir($mappingDirectory)) {
throw new \InvalidArgumentException(sprintf('Invalid Doctrine mapping path given. Cannot load Doctrine mapping/bundle named "%s".', $mappingName));
}
$this->drivers[$mappingConfig['type']][$mappingConfig['prefix']] = realpath($mappingDirectory) ?: $mappingDirectory;
}
/**
* If this is a bundle controlled mapping all the missing information can be autodetected by this method.
*
* Returns false when autodetection failed, an array of the completed information otherwise.
*
* @return array|false
*/
protected function getMappingDriverBundleConfigDefaults(array $bundleConfig, \ReflectionClass $bundle, ContainerBuilder $container)
{
$bundleDir = \dirname($bundle->getFileName());
if (!$bundleConfig['type']) {
$bundleConfig['type'] = $this->detectMetadataDriver($bundleDir, $container);
}
if (!$bundleConfig['type']) {
// skip this bundle, no mapping information was found.
return false;
}
if (!$bundleConfig['dir']) {
if (\in_array($bundleConfig['type'], ['annotation', 'staticphp'])) {
$bundleConfig['dir'] = $bundleDir.'/'.$this->getMappingObjectDefaultName();
} else {
$bundleConfig['dir'] = $bundleDir.'/'.$this->getMappingResourceConfigDirectory();
}
} else {
$bundleConfig['dir'] = $bundleDir.'/'.$bundleConfig['dir'];
}
if (!$bundleConfig['prefix']) {
$bundleConfig['prefix'] = $bundle->getNamespaceName().'\\'.$this->getMappingObjectDefaultName();
}
return $bundleConfig;
}
/**
* Register all the collected mapping information with the object manager by registering the appropriate mapping drivers.
*
* @param array $objectManager
* @param ContainerBuilder $container A ContainerBuilder instance
*/
protected function registerMappingDrivers($objectManager, ContainerBuilder $container)
{
// configure metadata driver for each bundle based on the type of mapping files found
if ($container->hasDefinition($this->getObjectManagerElementName($objectManager['name'].'_metadata_driver'))) {
$chainDriverDef = $container->getDefinition($this->getObjectManagerElementName($objectManager['name'].'_metadata_driver'));
} else {
$chainDriverDef = new Definition('%'.$this->getObjectManagerElementName('metadata.driver_chain.class%'));
$chainDriverDef->setPublic(false);
}
foreach ($this->drivers as $driverType => $driverPaths) {
$mappingService = $this->getObjectManagerElementName($objectManager['name'].'_'.$driverType.'_metadata_driver');
if ($container->hasDefinition($mappingService)) {
$mappingDriverDef = $container->getDefinition($mappingService);
$args = $mappingDriverDef->getArguments();
if ('annotation' == $driverType) {
$args[1] = array_merge(array_values($driverPaths), $args[1]);
} else {
$args[0] = array_merge(array_values($driverPaths), $args[0]);
}
$mappingDriverDef->setArguments($args);
} elseif ('annotation' == $driverType) {
$mappingDriverDef = new Definition('%'.$this->getObjectManagerElementName('metadata.'.$driverType.'.class%'), [
new Reference($this->getObjectManagerElementName('metadata.annotation_reader')),
array_values($driverPaths),
]);
} else {
$mappingDriverDef = new Definition('%'.$this->getObjectManagerElementName('metadata.'.$driverType.'.class%'), [
array_values($driverPaths),
]);
}
$mappingDriverDef->setPublic(false);
if (false !== strpos($mappingDriverDef->getClass(), 'yml') || false !== strpos($mappingDriverDef->getClass(), 'xml')) {
$mappingDriverDef->setArguments([array_flip($driverPaths)]);
$mappingDriverDef->addMethodCall('setGlobalBasename', ['mapping']);
}
$container->setDefinition($mappingService, $mappingDriverDef);
foreach ($driverPaths as $prefix => $driverPath) {
$chainDriverDef->addMethodCall('addDriver', [new Reference($mappingService), $prefix]);
}
}
$container->setDefinition($this->getObjectManagerElementName($objectManager['name'].'_metadata_driver'), $chainDriverDef);
}
/**
* Assertion if the specified mapping information is valid.
*
* @param array $mappingConfig
* @param string $objectManagerName
*
* @throws \InvalidArgumentException
*/
protected function assertValidMappingConfiguration(array $mappingConfig, $objectManagerName)
{
if (!$mappingConfig['type'] || !$mappingConfig['dir'] || !$mappingConfig['prefix']) {
throw new \InvalidArgumentException(sprintf('Mapping definitions for Doctrine manager "%s" require at least the "type", "dir" and "prefix" options.', $objectManagerName));
}
if (!is_dir($mappingConfig['dir'])) {
throw new \InvalidArgumentException(sprintf('Specified non-existing directory "%s" as Doctrine mapping source.', $mappingConfig['dir']));
}
if (!\in_array($mappingConfig['type'], ['xml', 'yml', 'annotation', 'php', 'staticphp'])) {
throw new \InvalidArgumentException(sprintf('Can only configure "xml", "yml", "annotation", "php" or '.
'"staticphp" through the DoctrineBundle. Use your own bundle to configure other metadata drivers. '.
'You can register them by adding a new driver to the '.
'"%s" service definition.', $this->getObjectManagerElementName($objectManagerName.'_metadata_driver')
));
}
}
/**
* Detects what metadata driver to use for the supplied directory.
*
* @param string $dir A directory path
* @param ContainerBuilder $container A ContainerBuilder instance
*
* @return string|null A metadata driver short name, if one can be detected
*/
protected function detectMetadataDriver($dir, ContainerBuilder $container)
{
$configPath = $this->getMappingResourceConfigDirectory();
$extension = $this->getMappingResourceExtension();
if (glob($dir.'/'.$configPath.'/*.'.$extension.'.xml')) {
$driver = 'xml';
} elseif (glob($dir.'/'.$configPath.'/*.'.$extension.'.yml')) {
$driver = 'yml';
} elseif (glob($dir.'/'.$configPath.'/*.'.$extension.'.php')) {
$driver = 'php';
} else {
// add the closest existing directory as a resource
$resource = $dir.'/'.$configPath;
while (!is_dir($resource)) {
$resource = \dirname($resource);
}
$container->fileExists($resource, false);
return $container->fileExists($dir.'/'.$this->getMappingObjectDefaultName(), false) ? 'annotation' : null;
}
$container->fileExists($dir.'/'.$configPath, false);
return $driver;
}
/**
* Loads a configured object manager metadata, query or result cache driver.
*
* @param array $objectManager A configured object manager
* @param ContainerBuilder $container A ContainerBuilder instance
* @param string $cacheName
*
* @throws \InvalidArgumentException in case of unknown driver type
*/
protected function loadObjectManagerCacheDriver(array $objectManager, ContainerBuilder $container, $cacheName)
{
$this->loadCacheDriver($cacheName, $objectManager['name'], $objectManager[$cacheName.'_driver'], $container);
}
/**
* Loads a cache driver.
*
* @param string $cacheName The cache driver name
* @param string $objectManagerName The object manager name
* @param array $cacheDriver The cache driver mapping
* @param ContainerBuilder $container The ContainerBuilder instance
*
* @return string
*
* @throws \InvalidArgumentException
*/
protected function loadCacheDriver($cacheName, $objectManagerName, array $cacheDriver, ContainerBuilder $container)
{
$cacheDriverServiceId = $this->getObjectManagerElementName($objectManagerName.'_'.$cacheName);
switch ($cacheDriver['type']) {
case 'service':
$container->setAlias($cacheDriverServiceId, new Alias($cacheDriver['id'], false));
return $cacheDriverServiceId;
case 'memcached':
$memcachedClass = !empty($cacheDriver['class']) ? $cacheDriver['class'] : '%'.$this->getObjectManagerElementName('cache.memcached.class').'%';
$memcachedInstanceClass = !empty($cacheDriver['instance_class']) ? $cacheDriver['instance_class'] : '%'.$this->getObjectManagerElementName('cache.memcached_instance.class').'%';
$memcachedHost = !empty($cacheDriver['host']) ? $cacheDriver['host'] : '%'.$this->getObjectManagerElementName('cache.memcached_host').'%';
$memcachedPort = !empty($cacheDriver['port']) ? $cacheDriver['port'] : '%'.$this->getObjectManagerElementName('cache.memcached_port').'%';
$cacheDef = new Definition($memcachedClass);
$memcachedInstance = new Definition($memcachedInstanceClass);
$memcachedInstance->setPrivate(true);
$memcachedInstance->addMethodCall('addServer', [
$memcachedHost, $memcachedPort,
]);
$container->setDefinition($this->getObjectManagerElementName(sprintf('%s_memcached_instance', $objectManagerName)), $memcachedInstance);
$cacheDef->addMethodCall('setMemcached', [new Reference($this->getObjectManagerElementName(sprintf('%s_memcached_instance', $objectManagerName)))]);
break;
case 'redis':
$redisClass = !empty($cacheDriver['class']) ? $cacheDriver['class'] : '%'.$this->getObjectManagerElementName('cache.redis.class').'%';
$redisInstanceClass = !empty($cacheDriver['instance_class']) ? $cacheDriver['instance_class'] : '%'.$this->getObjectManagerElementName('cache.redis_instance.class').'%';
$redisHost = !empty($cacheDriver['host']) ? $cacheDriver['host'] : '%'.$this->getObjectManagerElementName('cache.redis_host').'%';
$redisPort = !empty($cacheDriver['port']) ? $cacheDriver['port'] : '%'.$this->getObjectManagerElementName('cache.redis_port').'%';
$cacheDef = new Definition($redisClass);
$redisInstance = new Definition($redisInstanceClass);
$redisInstance->setPrivate(true);
$redisInstance->addMethodCall('connect', [
$redisHost, $redisPort,
]);
$container->setDefinition($this->getObjectManagerElementName(sprintf('%s_redis_instance', $objectManagerName)), $redisInstance);
$cacheDef->addMethodCall('setRedis', [new Reference($this->getObjectManagerElementName(sprintf('%s_redis_instance', $objectManagerName)))]);
break;
case 'apc':
case 'apcu':
case 'array':
case 'xcache':
case 'wincache':
case 'zenddata':
$cacheDef = new Definition('%'.$this->getObjectManagerElementName(sprintf('cache.%s.class', $cacheDriver['type'])).'%');
break;
default:
throw new \InvalidArgumentException(sprintf('"%s" is an unrecognized Doctrine cache driver.', $cacheDriver['type']));
}
$cacheDef->setPublic(false);
if (!isset($cacheDriver['namespace'])) {
// generate a unique namespace for the given application
if ($container->hasParameter('cache.prefix.seed')) {
$seed = '.'.$container->getParameterBag()->resolveValue($container->getParameter('cache.prefix.seed'));
} else {
$seed = '_'.$container->getParameter('kernel.project_dir');
}
$seed .= '.'.$container->getParameter('kernel.container_class');
$namespace = 'sf_'.$this->getMappingResourceExtension().'_'.$objectManagerName.'_'.ContainerBuilder::hash($seed);
$cacheDriver['namespace'] = $namespace;
}
$cacheDef->addMethodCall('setNamespace', [$cacheDriver['namespace']]);
$container->setDefinition($cacheDriverServiceId, $cacheDef);
return $cacheDriverServiceId;
}
/**
* Returns a modified version of $managerConfigs.
*
* The manager called $autoMappedManager will map all bundles that are not mapped by other managers.
*
* @return array The modified version of $managerConfigs
*/
protected function fixManagersAutoMappings(array $managerConfigs, array $bundles)
{
if ($autoMappedManager = $this->validateAutoMapping($managerConfigs)) {
foreach (array_keys($bundles) as $bundle) {
foreach ($managerConfigs as $manager) {
if (isset($manager['mappings'][$bundle])) {
continue 2;
}
}
$managerConfigs[$autoMappedManager]['mappings'][$bundle] = [
'mapping' => true,
'is_bundle' => true,
];
}
$managerConfigs[$autoMappedManager]['auto_mapping'] = false;
}
return $managerConfigs;
}
/**
* Prefixes the relative dependency injection container path with the object manager prefix.
*
* @example $name is 'entity_manager' then the result would be 'doctrine.orm.entity_manager'
*
* @param string $name
*
* @return string
*/
abstract protected function getObjectManagerElementName($name);
/**
* Noun that describes the mapped objects such as Entity or Document.
*
* Will be used for autodetection of persistent objects directory.
*
* @return string
*/
abstract protected function getMappingObjectDefaultName();
/**
* Relative path from the bundle root to the directory where mapping files reside.
*
* @return string
*/
abstract protected function getMappingResourceConfigDirectory();
/**
* Extension used by the mapping files.
*
* @return string
*/
abstract protected function getMappingResourceExtension();
/**
* Search for a manager that is declared as 'auto_mapping' = true.
*
* @return string|null The name of the manager. If no one manager is found, returns null
*
* @throws \LogicException
*/
private function validateAutoMapping(array $managerConfigs)
{
$autoMappedManager = null;
foreach ($managerConfigs as $name => $manager) {
if (!$manager['auto_mapping']) {
continue;
}
if (null !== $autoMappedManager) {
throw new \LogicException(sprintf('You cannot enable "auto_mapping" on more than one manager at the same time (found in "%s" and %s").', $autoMappedManager, $name));
}
$autoMappedManager = $name;
}
return $autoMappedManager;
}
}

View File

@ -0,0 +1,62 @@
<?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\Doctrine\DependencyInjection\CompilerPass;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
/**
* Registers additional validators.
*
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class DoctrineValidationPass implements CompilerPassInterface
{
private $managerType;
public function __construct(string $managerType)
{
$this->managerType = $managerType;
}
/**
* {@inheritdoc}
*/
public function process(ContainerBuilder $container)
{
$this->updateValidatorMappingFiles($container, 'xml', 'xml');
$this->updateValidatorMappingFiles($container, 'yaml', 'yml');
}
/**
* Gets the validation mapping files for the format and extends them with
* files matching a doctrine search pattern (Resources/config/validation.orm.xml).
*/
private function updateValidatorMappingFiles(ContainerBuilder $container, string $mapping, string $extension)
{
if (!$container->hasParameter('validator.mapping.loader.'.$mapping.'_files_loader.mapping_files')) {
return;
}
$files = $container->getParameter('validator.mapping.loader.'.$mapping.'_files_loader.mapping_files');
$validationPath = 'Resources/config/validation.'.$this->managerType.'.'.$extension;
foreach ($container->getParameter('kernel.bundles') as $bundle) {
$reflection = new \ReflectionClass($bundle);
if ($container->fileExists($file = \dirname($reflection->getFileName()).'/'.$validationPath)) {
$files[] = $file;
}
}
$container->setParameter('validator.mapping.loader.'.$mapping.'_files_loader.mapping_files', $files);
}
}

View File

@ -0,0 +1,154 @@
<?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\Doctrine\DependencyInjection\CompilerPass;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\Reference;
/**
* Registers event listeners and subscribers to the available doctrine connections.
*
* @author Jeremy Mikola <jmikola@gmail.com>
* @author Alexander <iam.asm89@gmail.com>
* @author David Maicher <mail@dmaicher.de>
*/
class RegisterEventListenersAndSubscribersPass implements CompilerPassInterface
{
private $connections;
private $eventManagers;
private $managerTemplate;
private $tagPrefix;
/**
* @param string $connections Parameter ID for connections
* @param string $managerTemplate sprintf() template for generating the event
* manager's service ID for a connection name
* @param string $tagPrefix Tag prefix for listeners and subscribers
*/
public function __construct(string $connections, string $managerTemplate, string $tagPrefix)
{
$this->connections = $connections;
$this->managerTemplate = $managerTemplate;
$this->tagPrefix = $tagPrefix;
}
/**
* {@inheritdoc}
*/
public function process(ContainerBuilder $container)
{
if (!$container->hasParameter($this->connections)) {
return;
}
$this->connections = $container->getParameter($this->connections);
$this->addTaggedSubscribers($container);
$this->addTaggedListeners($container);
}
private function addTaggedSubscribers(ContainerBuilder $container)
{
$subscriberTag = $this->tagPrefix.'.event_subscriber';
$taggedSubscribers = $this->findAndSortTags($subscriberTag, $container);
foreach ($taggedSubscribers as $taggedSubscriber) {
list($id, $tag) = $taggedSubscriber;
$connections = isset($tag['connection']) ? [$tag['connection']] : array_keys($this->connections);
foreach ($connections as $con) {
if (!isset($this->connections[$con])) {
throw new RuntimeException(sprintf('The Doctrine connection "%s" referenced in service "%s" does not exist. Available connections names: %s', $con, $id, implode(', ', array_keys($this->connections))));
}
$this->getEventManagerDef($container, $con)->addMethodCall('addEventSubscriber', [new Reference($id)]);
}
}
}
private function addTaggedListeners(ContainerBuilder $container)
{
$listenerTag = $this->tagPrefix.'.event_listener';
$taggedListeners = $this->findAndSortTags($listenerTag, $container);
$listenerRefs = [];
foreach ($taggedListeners as $taggedListener) {
list($id, $tag) = $taggedListener;
if (!isset($tag['event'])) {
throw new InvalidArgumentException(sprintf('Doctrine event listener "%s" must specify the "event" attribute.', $id));
}
$connections = isset($tag['connection']) ? [$tag['connection']] : array_keys($this->connections);
foreach ($connections as $con) {
if (!isset($this->connections[$con])) {
throw new RuntimeException(sprintf('The Doctrine connection "%s" referenced in service "%s" does not exist. Available connections names: %s', $con, $id, implode(', ', array_keys($this->connections))));
}
$listenerRefs[$con][$id] = new Reference($id);
// we add one call per event per service so we have the correct order
$this->getEventManagerDef($container, $con)->addMethodCall('addEventListener', [[$tag['event']], $id]);
}
}
// replace service container argument of event managers with smaller service locator
// so services can even remain private
foreach ($listenerRefs as $connection => $refs) {
$this->getEventManagerDef($container, $connection)
->replaceArgument(0, ServiceLocatorTagPass::register($container, $refs));
}
}
private function getEventManagerDef(ContainerBuilder $container, $name)
{
if (!isset($this->eventManagers[$name])) {
$this->eventManagers[$name] = $container->getDefinition(sprintf($this->managerTemplate, $name));
}
return $this->eventManagers[$name];
}
/**
* Finds and orders all service tags with the given name by their priority.
*
* The order of additions must be respected for services having the same priority,
* and knowing that the \SplPriorityQueue class does not respect the FIFO method,
* we should not use this class.
*
* @see https://bugs.php.net/bug.php?id=53710
* @see https://bugs.php.net/bug.php?id=60926
*
* @param string $tagName
* @param ContainerBuilder $container
*
* @return array
*/
private function findAndSortTags($tagName, ContainerBuilder $container)
{
$sortedTags = [];
foreach ($container->findTaggedServiceIds($tagName, true) as $serviceId => $tags) {
foreach ($tags as $attributes) {
$priority = isset($attributes['priority']) ? $attributes['priority'] : 0;
$sortedTags[$priority][] = [$serviceId, $attributes];
}
}
if ($sortedTags) {
krsort($sortedTags);
$sortedTags = array_merge(...$sortedTags);
}
return $sortedTags;
}
}

View File

@ -0,0 +1,244 @@
<?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\Doctrine\DependencyInjection\CompilerPass;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Reference;
/**
* Base class for the doctrine bundles to provide a compiler pass class that
* helps to register doctrine mappings.
*
* The compiler pass is meant to register the mappings with the metadata
* chain driver corresponding to one of the object managers.
*
* For concrete implementations, see the RegisterXyMappingsPass classes
* in the DoctrineBundle resp.
* DoctrineMongodbBundle, DoctrineCouchdbBundle and DoctrinePhpcrBundle.
*
* @author David Buchmann <david@liip.ch>
*/
abstract class RegisterMappingsPass implements CompilerPassInterface
{
/**
* DI object for the driver to use, either a service definition for a
* private service or a reference for a public service.
*
* @var Definition|Reference
*/
protected $driver;
/**
* List of namespaces handled by the driver.
*
* @var string[]
*/
protected $namespaces;
/**
* List of potential container parameters that hold the object manager name
* to register the mappings with the correct metadata driver, for example
* ['acme.manager', 'doctrine.default_entity_manager'].
*
* @var string[]
*/
protected $managerParameters;
/**
* Naming pattern of the metadata chain driver service ids, for example
* 'doctrine.orm.%s_metadata_driver'.
*
* @var string
*/
protected $driverPattern;
/**
* A name for a parameter in the container. If set, this compiler pass will
* only do anything if the parameter is present. (But regardless of the
* value of that parameter.
*
* @var string|false
*/
protected $enabledParameter;
/**
* Naming pattern for the configuration service id, for example
* 'doctrine.orm.%s_configuration'.
*
* @var string
*/
private $configurationPattern;
/**
* Method name to call on the configuration service. This depends on the
* Doctrine implementation. For example addEntityNamespace.
*
* @var string
*/
private $registerAliasMethodName;
/**
* Map of alias to namespace.
*
* @var string[]
*/
private $aliasMap;
/**
* The $managerParameters is an ordered list of container parameters that could provide the
* name of the manager to register these namespaces and alias on. The first non-empty name
* is used, the others skipped.
*
* The $aliasMap parameter can be used to define bundle namespace shortcuts like the
* DoctrineBundle provides automatically for objects in the default Entity/Document folder.
*
* @param Definition|Reference $driver Driver DI definition or reference
* @param string[] $namespaces List of namespaces handled by $driver
* @param string[] $managerParameters list of container parameters that could
* hold the manager name
* @param string $driverPattern Pattern for the metadata driver service name
* @param string|false $enabledParameter Service container parameter that must be
* present to enable the mapping. Set to false
* to not do any check, optional.
* @param string $configurationPattern Pattern for the Configuration service name
* @param string $registerAliasMethodName Name of Configuration class method to
* register alias
* @param string[] $aliasMap Map of alias to namespace
*/
public function __construct($driver, array $namespaces, array $managerParameters, string $driverPattern, $enabledParameter = false, string $configurationPattern = '', string $registerAliasMethodName = '', array $aliasMap = [])
{
$this->driver = $driver;
$this->namespaces = $namespaces;
$this->managerParameters = $managerParameters;
$this->driverPattern = $driverPattern;
$this->enabledParameter = $enabledParameter;
if (\count($aliasMap) && (!$configurationPattern || !$registerAliasMethodName)) {
throw new \InvalidArgumentException('configurationPattern and registerAliasMethodName are required to register namespace alias');
}
$this->configurationPattern = $configurationPattern;
$this->registerAliasMethodName = $registerAliasMethodName;
$this->aliasMap = $aliasMap;
}
/**
* Register mappings and alias with the metadata drivers.
*/
public function process(ContainerBuilder $container)
{
if (!$this->enabled($container)) {
return;
}
$mappingDriverDef = $this->getDriver($container);
$chainDriverDefService = $this->getChainDriverServiceName($container);
// Definition for a Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain
$chainDriverDef = $container->getDefinition($chainDriverDefService);
foreach ($this->namespaces as $namespace) {
$chainDriverDef->addMethodCall('addDriver', [$mappingDriverDef, $namespace]);
}
if (!\count($this->aliasMap)) {
return;
}
$configurationServiceName = $this->getConfigurationServiceName($container);
// Definition of the Doctrine\...\Configuration class specific to the Doctrine flavour.
$configurationServiceDefinition = $container->getDefinition($configurationServiceName);
foreach ($this->aliasMap as $alias => $namespace) {
$configurationServiceDefinition->addMethodCall($this->registerAliasMethodName, [$alias, $namespace]);
}
}
/**
* Get the service name of the metadata chain driver that the mappings
* should be registered with.
*
* @return string The name of the chain driver service
*
* @throws InvalidArgumentException if non of the managerParameters has a
* non-empty value
*/
protected function getChainDriverServiceName(ContainerBuilder $container)
{
return sprintf($this->driverPattern, $this->getManagerName($container));
}
/**
* Create the service definition for the metadata driver.
*
* @param ContainerBuilder $container Passed on in case an extending class
* needs access to the container
*
* @return Definition|Reference the metadata driver to add to all chain drivers
*/
protected function getDriver(ContainerBuilder $container)
{
return $this->driver;
}
/**
* Get the service name from the pattern and the configured manager name.
*
* @return string a service definition name
*
* @throws InvalidArgumentException if none of the managerParameters has a
* non-empty value
*/
private function getConfigurationServiceName(ContainerBuilder $container)
{
return sprintf($this->configurationPattern, $this->getManagerName($container));
}
/**
* Determine the manager name.
*
* The default implementation loops over the managerParameters and returns
* the first non-empty parameter.
*
* @return string The name of the active manager
*
* @throws InvalidArgumentException if none of the managerParameters is found in the container
*/
private function getManagerName(ContainerBuilder $container)
{
foreach ($this->managerParameters as $param) {
if ($container->hasParameter($param)) {
$name = $container->getParameter($param);
if ($name) {
return $name;
}
}
}
throw new InvalidArgumentException(sprintf(
'Could not find the manager name parameter in the container. Tried the following parameter names: "%s"',
implode('", "', $this->managerParameters)
));
}
/**
* Determine whether this mapping should be activated or not. This allows
* to take this decision with the container builder available.
*
* This default implementation checks if the class has the enabledParameter
* configured and if so if that parameter is present in the container.
*
* @return bool whether this compiler pass really should register the mappings
*/
protected function enabled(ContainerBuilder $container)
{
return !$this->enabledParameter || $container->hasParameter($this->enabledParameter);
}
}

View File

@ -0,0 +1,61 @@
<?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\Doctrine\DependencyInjection\Security\UserProvider;
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider\UserProviderFactoryInterface;
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
/**
* EntityFactory creates services for Doctrine user provider.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Christophe Coevoet <stof@notk.org>
*/
class EntityFactory implements UserProviderFactoryInterface
{
private $key;
private $providerId;
public function __construct(string $key, string $providerId)
{
$this->key = $key;
$this->providerId = $providerId;
}
public function create(ContainerBuilder $container, $id, $config)
{
$container
->setDefinition($id, new ChildDefinition($this->providerId))
->addArgument($config['class'])
->addArgument($config['property'])
->addArgument($config['manager_name'])
;
}
public function getKey()
{
return $this->key;
}
public function addConfiguration(NodeDefinition $node)
{
$node
->children()
->scalarNode('class')->isRequired()->cannotBeEmpty()->end()
->scalarNode('property')->defaultNull()->end()
->scalarNode('manager_name')->defaultNull()->end()
->end()
;
}
}

View File

@ -0,0 +1,149 @@
<?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\Doctrine\Form\ChoiceList;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\Form\ChoiceList\ArrayChoiceList;
use Symfony\Component\Form\ChoiceList\ChoiceListInterface;
use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface;
/**
* Loads choices using a Doctrine object manager.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class DoctrineChoiceLoader implements ChoiceLoaderInterface
{
private $manager;
private $class;
private $idReader;
private $objectLoader;
/**
* @var ChoiceListInterface
*/
private $choiceList;
/**
* Creates a new choice loader.
*
* Optionally, an implementation of {@link EntityLoaderInterface} can be
* passed which optimizes the object loading for one of the Doctrine
* mapper implementations.
*
* @param ObjectManager $manager The object manager
* @param string $class The class name of the loaded objects
* @param IdReader $idReader The reader for the object IDs
* @param EntityLoaderInterface|null $objectLoader The objects loader
*/
public function __construct(ObjectManager $manager, string $class, IdReader $idReader = null, EntityLoaderInterface $objectLoader = null)
{
$classMetadata = $manager->getClassMetadata($class);
$this->manager = $manager;
$this->class = $classMetadata->getName();
$this->idReader = $idReader ?: new IdReader($manager, $classMetadata);
$this->objectLoader = $objectLoader;
}
/**
* {@inheritdoc}
*/
public function loadChoiceList($value = null)
{
if ($this->choiceList) {
return $this->choiceList;
}
$objects = $this->objectLoader
? $this->objectLoader->getEntities()
: $this->manager->getRepository($this->class)->findAll();
return $this->choiceList = new ArrayChoiceList($objects, $value);
}
/**
* {@inheritdoc}
*/
public function loadValuesForChoices(array $choices, $value = null)
{
// Performance optimization
if (empty($choices)) {
return [];
}
// Optimize performance for single-field identifiers. We already
// know that the IDs are used as values
$optimize = null === $value || \is_array($value) && $value[0] === $this->idReader;
// Attention: This optimization does not check choices for existence
if ($optimize && !$this->choiceList && $this->idReader->isSingleId()) {
$values = [];
// Maintain order and indices of the given objects
foreach ($choices as $i => $object) {
if ($object instanceof $this->class) {
// Make sure to convert to the right format
$values[$i] = (string) $this->idReader->getIdValue($object);
}
}
return $values;
}
return $this->loadChoiceList($value)->getValuesForChoices($choices);
}
/**
* {@inheritdoc}
*/
public function loadChoicesForValues(array $values, $value = null)
{
// Performance optimization
// Also prevents the generation of "WHERE id IN ()" queries through the
// object loader. At least with MySQL and on the development machine
// this was tested on, no exception was thrown for such invalid
// statements, consequently no test fails when this code is removed.
// https://github.com/symfony/symfony/pull/8981#issuecomment-24230557
if (empty($values)) {
return [];
}
// Optimize performance in case we have an object loader and
// a single-field identifier
$optimize = null === $value || \is_array($value) && $this->idReader === $value[0];
if ($optimize && !$this->choiceList && $this->objectLoader && $this->idReader->isSingleId()) {
$unorderedObjects = $this->objectLoader->getEntitiesByIds($this->idReader->getIdField(), $values);
$objectsById = [];
$objects = [];
// Maintain order and indices from the given $values
// An alternative approach to the following loop is to add the
// "INDEX BY" clause to the Doctrine query in the loader,
// but I'm not sure whether that's doable in a generic fashion.
foreach ($unorderedObjects as $object) {
$objectsById[(string) $this->idReader->getIdValue($object)] = $object;
}
foreach ($values as $i => $id) {
if (isset($objectsById[$id])) {
$objects[$i] = $objectsById[$id];
}
}
return $objects;
}
return $this->loadChoiceList($value)->getChoicesForValues($values);
}
}

View File

@ -0,0 +1,39 @@
<?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\Doctrine\Form\ChoiceList;
/**
* Custom loader for entities in the choice list.
*
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
interface EntityLoaderInterface
{
/**
* Returns an array of entities that are valid choices in the corresponding choice list.
*
* @return array The entities
*/
public function getEntities();
/**
* Returns an array of entities matching the given identifiers.
*
* @param string $identifier The identifier field of the object. This method
* is not applicable for fields with multiple
* identifiers.
* @param array $values The values of the identifiers
*
* @return array The entities
*/
public function getEntitiesByIds($identifier, array $values);
}

View File

@ -0,0 +1,123 @@
<?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\Doctrine\Form\ChoiceList;
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\Form\Exception\RuntimeException;
/**
* A utility for reading object IDs.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @internal
*/
class IdReader
{
private $om;
private $classMetadata;
private $singleId;
private $intId;
private $idField;
/**
* @var IdReader|null
*/
private $associationIdReader;
public function __construct(ObjectManager $om, ClassMetadata $classMetadata)
{
$ids = $classMetadata->getIdentifierFieldNames();
$idType = $classMetadata->getTypeOfField(current($ids));
$this->om = $om;
$this->classMetadata = $classMetadata;
$this->singleId = 1 === \count($ids);
$this->intId = $this->singleId && \in_array($idType, ['integer', 'smallint', 'bigint']);
$this->idField = current($ids);
// single field association are resolved, since the schema column could be an int
if ($this->singleId && $classMetadata->hasAssociation($this->idField)) {
$this->associationIdReader = new self($om, $om->getClassMetadata(
$classMetadata->getAssociationTargetClass($this->idField)
));
$this->singleId = $this->associationIdReader->isSingleId();
$this->intId = $this->associationIdReader->isIntId();
}
}
/**
* Returns whether the class has a single-column ID.
*
* @return bool returns `true` if the class has a single-column ID and
* `false` otherwise
*/
public function isSingleId(): bool
{
return $this->singleId;
}
/**
* Returns whether the class has a single-column integer ID.
*
* @return bool returns `true` if the class has a single-column integer ID
* and `false` otherwise
*/
public function isIntId(): bool
{
return $this->intId;
}
/**
* Returns the ID value for an object.
*
* This method assumes that the object has a single-column ID.
*
* @param object $object The object
*
* @return mixed The ID value
*/
public function getIdValue($object)
{
if (!$object) {
return;
}
if (!$this->om->contains($object)) {
throw new RuntimeException(sprintf('Entity of type "%s" passed to the choice field must be managed. Maybe you forget to persist it in the entity manager?', \get_class($object)));
}
$this->om->initializeObject($object);
$idValue = current($this->classMetadata->getIdentifierValues($object));
if ($this->associationIdReader) {
$idValue = $this->associationIdReader->getIdValue($idValue);
}
return $idValue;
}
/**
* Returns the name of the ID field.
*
* This method assumes that the object has a single-column ID.
*
* @return string The name of the ID field
*/
public function getIdField(): string
{
return $this->idField;
}
}

View File

@ -0,0 +1,94 @@
<?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\Doctrine\Form\ChoiceList;
use Doctrine\DBAL\Connection;
use Doctrine\ORM\QueryBuilder;
/**
* Loads entities using a {@link QueryBuilder} instance.
*
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class ORMQueryBuilderLoader implements EntityLoaderInterface
{
/**
* Contains the query builder that builds the query for fetching the
* entities.
*
* This property should only be accessed through queryBuilder.
*
* @var QueryBuilder
*/
private $queryBuilder;
/**
* Construct an ORM Query Builder Loader.
*
* @param QueryBuilder $queryBuilder The query builder for creating the query builder
*/
public function __construct(QueryBuilder $queryBuilder)
{
$this->queryBuilder = $queryBuilder;
}
/**
* {@inheritdoc}
*/
public function getEntities()
{
return $this->queryBuilder->getQuery()->execute();
}
/**
* {@inheritdoc}
*/
public function getEntitiesByIds($identifier, array $values)
{
$qb = clone $this->queryBuilder;
$alias = current($qb->getRootAliases());
$parameter = 'ORMQueryBuilderLoader_getEntitiesByIds_'.$identifier;
$parameter = str_replace('.', '_', $parameter);
$where = $qb->expr()->in($alias.'.'.$identifier, ':'.$parameter);
// Guess type
$entity = current($qb->getRootEntities());
$metadata = $qb->getEntityManager()->getClassMetadata($entity);
if (\in_array($metadata->getTypeOfField($identifier), ['integer', 'bigint', 'smallint'])) {
$parameterType = Connection::PARAM_INT_ARRAY;
// Filter out non-integer values (e.g. ""). If we don't, some
// databases such as PostgreSQL fail.
$values = array_values(array_filter($values, function ($v) {
return (string) $v === (string) (int) $v || ctype_digit($v);
}));
} elseif (\in_array($metadata->getTypeOfField($identifier), ['uuid', 'guid'])) {
$parameterType = Connection::PARAM_STR_ARRAY;
// Like above, but we just filter out empty strings.
$values = array_values(array_filter($values, function ($v) {
return '' !== (string) $v;
}));
} else {
$parameterType = Connection::PARAM_STR_ARRAY;
}
if (!$values) {
return [];
}
return $qb->andWhere($where)
->getQuery()
->setParameter($parameter, $values, $parameterType)
->getResult();
}
}

View File

@ -0,0 +1,67 @@
<?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\Doctrine\Form\DataTransformer;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class CollectionToArrayTransformer implements DataTransformerInterface
{
/**
* Transforms a collection into an array.
*
* @return mixed An array of entities
*
* @throws TransformationFailedException
*/
public function transform($collection)
{
if (null === $collection) {
return [];
}
// For cases when the collection getter returns $collection->toArray()
// in order to prevent modifications of the returned collection
if (\is_array($collection)) {
return $collection;
}
if (!$collection instanceof Collection) {
throw new TransformationFailedException('Expected a Doctrine\Common\Collections\Collection object.');
}
return $collection->toArray();
}
/**
* Transforms choice keys into entities.
*
* @param mixed $array An array of entities
*
* @return Collection A collection of entities
*/
public function reverseTransform($array)
{
if ('' === $array || null === $array) {
$array = [];
} else {
$array = (array) $array;
}
return new ArrayCollection($array);
}
}

View File

@ -0,0 +1,38 @@
<?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\Doctrine\Form;
use Doctrine\Common\Persistence\ManagerRegistry;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractExtension;
class DoctrineOrmExtension extends AbstractExtension
{
protected $registry;
public function __construct(ManagerRegistry $registry)
{
$this->registry = $registry;
}
protected function loadTypes()
{
return [
new EntityType($this->registry),
];
}
protected function loadTypeGuesser()
{
return new DoctrineOrmTypeGuesser($this->registry);
}
}

View File

@ -0,0 +1,192 @@
<?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\Doctrine\Form;
use Doctrine\Common\Persistence\ManagerRegistry;
use Doctrine\Common\Persistence\Mapping\MappingException;
use Doctrine\Common\Persistence\Proxy;
use Doctrine\DBAL\Types\Type;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Doctrine\ORM\Mapping\MappingException as LegacyMappingException;
use Symfony\Component\Form\FormTypeGuesserInterface;
use Symfony\Component\Form\Guess\Guess;
use Symfony\Component\Form\Guess\TypeGuess;
use Symfony\Component\Form\Guess\ValueGuess;
class DoctrineOrmTypeGuesser implements FormTypeGuesserInterface
{
protected $registry;
private $cache = [];
public function __construct(ManagerRegistry $registry)
{
$this->registry = $registry;
}
/**
* {@inheritdoc}
*/
public function guessType($class, $property)
{
if (!$ret = $this->getMetadata($class)) {
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TextType', [], Guess::LOW_CONFIDENCE);
}
list($metadata, $name) = $ret;
if ($metadata->hasAssociation($property)) {
$multiple = $metadata->isCollectionValuedAssociation($property);
$mapping = $metadata->getAssociationMapping($property);
return new TypeGuess('Symfony\Bridge\Doctrine\Form\Type\EntityType', ['em' => $name, 'class' => $mapping['targetEntity'], 'multiple' => $multiple], Guess::HIGH_CONFIDENCE);
}
switch ($metadata->getTypeOfField($property)) {
case Type::TARRAY:
case Type::SIMPLE_ARRAY:
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\CollectionType', [], Guess::MEDIUM_CONFIDENCE);
case Type::BOOLEAN:
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\CheckboxType', [], Guess::HIGH_CONFIDENCE);
case Type::DATETIME:
case Type::DATETIMETZ:
case 'vardatetime':
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateTimeType', [], Guess::HIGH_CONFIDENCE);
case 'datetime_immutable':
case 'datetimetz_immutable':
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateTimeType', ['input' => 'datetime_immutable'], Guess::HIGH_CONFIDENCE);
case 'dateinterval':
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateIntervalType', [], Guess::HIGH_CONFIDENCE);
case Type::DATE:
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateType', [], Guess::HIGH_CONFIDENCE);
case 'date_immutable':
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateType', ['input' => 'datetime_immutable'], Guess::HIGH_CONFIDENCE);
case Type::TIME:
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TimeType', [], Guess::HIGH_CONFIDENCE);
case 'time_immutable':
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TimeType', ['input' => 'datetime_immutable'], Guess::HIGH_CONFIDENCE);
case Type::DECIMAL:
case Type::FLOAT:
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\NumberType', [], Guess::MEDIUM_CONFIDENCE);
case Type::INTEGER:
case Type::BIGINT:
case Type::SMALLINT:
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\IntegerType', [], Guess::MEDIUM_CONFIDENCE);
case Type::STRING:
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TextType', [], Guess::MEDIUM_CONFIDENCE);
case Type::TEXT:
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TextareaType', [], Guess::MEDIUM_CONFIDENCE);
default:
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TextType', [], Guess::LOW_CONFIDENCE);
}
}
/**
* {@inheritdoc}
*/
public function guessRequired($class, $property)
{
$classMetadatas = $this->getMetadata($class);
if (!$classMetadatas) {
return;
}
/** @var ClassMetadataInfo $classMetadata */
$classMetadata = $classMetadatas[0];
// Check whether the field exists and is nullable or not
if (isset($classMetadata->fieldMappings[$property])) {
if (!$classMetadata->isNullable($property) && Type::BOOLEAN !== $classMetadata->getTypeOfField($property)) {
return new ValueGuess(true, Guess::HIGH_CONFIDENCE);
}
return new ValueGuess(false, Guess::MEDIUM_CONFIDENCE);
}
// Check whether the association exists, is a to-one association and its
// join column is nullable or not
if ($classMetadata->isAssociationWithSingleJoinColumn($property)) {
$mapping = $classMetadata->getAssociationMapping($property);
if (!isset($mapping['joinColumns'][0]['nullable'])) {
// The "nullable" option defaults to true, in that case the
// field should not be required.
return new ValueGuess(false, Guess::HIGH_CONFIDENCE);
}
return new ValueGuess(!$mapping['joinColumns'][0]['nullable'], Guess::HIGH_CONFIDENCE);
}
}
/**
* {@inheritdoc}
*/
public function guessMaxLength($class, $property)
{
$ret = $this->getMetadata($class);
if ($ret && isset($ret[0]->fieldMappings[$property]) && !$ret[0]->hasAssociation($property)) {
$mapping = $ret[0]->getFieldMapping($property);
if (isset($mapping['length'])) {
return new ValueGuess($mapping['length'], Guess::HIGH_CONFIDENCE);
}
if (\in_array($ret[0]->getTypeOfField($property), [Type::DECIMAL, Type::FLOAT])) {
return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE);
}
}
}
/**
* {@inheritdoc}
*/
public function guessPattern($class, $property)
{
$ret = $this->getMetadata($class);
if ($ret && isset($ret[0]->fieldMappings[$property]) && !$ret[0]->hasAssociation($property)) {
if (\in_array($ret[0]->getTypeOfField($property), [Type::DECIMAL, Type::FLOAT])) {
return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE);
}
}
}
protected function getMetadata($class)
{
// normalize class name
$class = self::getRealClass(ltrim($class, '\\'));
if (\array_key_exists($class, $this->cache)) {
return $this->cache[$class];
}
$this->cache[$class] = null;
foreach ($this->registry->getManagers() as $name => $em) {
try {
return $this->cache[$class] = [$em->getClassMetadata($class), $name];
} catch (MappingException $e) {
// not an entity or mapped super class
} catch (LegacyMappingException $e) {
// not an entity or mapped super class, using Doctrine ORM 2.2
}
}
}
private static function getRealClass(string $class): string
{
if (false === $pos = strrpos($class, '\\'.Proxy::MARKER.'\\')) {
return $class;
}
return substr($class, $pos + Proxy::MARKER_LENGTH + 2);
}
}

View File

@ -0,0 +1,52 @@
<?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\Doctrine\Form\EventListener;
use Doctrine\Common\Collections\Collection;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
/**
* Merge changes from the request to a Doctrine\Common\Collections\Collection instance.
*
* This works with ORM, MongoDB and CouchDB instances of the collection interface.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @see Collection
*/
class MergeDoctrineCollectionListener implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
// Higher priority than core MergeCollectionListener so that this one
// is called before
return [
FormEvents::SUBMIT => [
['onSubmit', 5],
],
];
}
public function onSubmit(FormEvent $event)
{
$collection = $event->getForm()->getData();
$data = $event->getData();
// If all items were removed, call clear which has a higher
// performance on persistent collections
if ($collection instanceof Collection && 0 === \count($data)) {
$collection->clear();
}
}
}

View File

@ -0,0 +1,285 @@
<?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\Doctrine\Form\Type;
use Doctrine\Common\Persistence\ManagerRegistry;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Bridge\Doctrine\Form\ChoiceList\DoctrineChoiceLoader;
use Symfony\Bridge\Doctrine\Form\ChoiceList\EntityLoaderInterface;
use Symfony\Bridge\Doctrine\Form\ChoiceList\IdReader;
use Symfony\Bridge\Doctrine\Form\DataTransformer\CollectionToArrayTransformer;
use Symfony\Bridge\Doctrine\Form\EventListener\MergeDoctrineCollectionListener;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\ChoiceList\Factory\CachingFactoryDecorator;
use Symfony\Component\Form\Exception\RuntimeException;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Contracts\Service\ResetInterface;
abstract class DoctrineType extends AbstractType implements ResetInterface
{
/**
* @var ManagerRegistry
*/
protected $registry;
/**
* @var IdReader[]
*/
private $idReaders = [];
/**
* @var DoctrineChoiceLoader[]
*/
private $choiceLoaders = [];
/**
* Creates the label for a choice.
*
* For backwards compatibility, objects are cast to strings by default.
*
* @param object $choice The object
*
* @return string The string representation of the object
*
* @internal This method is public to be usable as callback. It should not
* be used in user code.
*/
public static function createChoiceLabel($choice)
{
return (string) $choice;
}
/**
* Creates the field name for a choice.
*
* This method is used to generate field names if the underlying object has
* a single-column integer ID. In that case, the value of the field is
* the ID of the object. That ID is also used as field name.
*
* @param object $choice The object
* @param int|string $key The choice key
* @param string $value The choice value. Corresponds to the object's
* ID here.
*
* @return string The field name
*
* @internal This method is public to be usable as callback. It should not
* be used in user code.
*/
public static function createChoiceName($choice, $key, $value)
{
return str_replace('-', '_', (string) $value);
}
/**
* Gets important parts from QueryBuilder that will allow to cache its results.
* For instance in ORM two query builders with an equal SQL string and
* equal parameters are considered to be equal.
*
* @param object $queryBuilder
*
* @return array|false Array with important QueryBuilder parts or false if
* they can't be determined
*
* @internal This method is public to be usable as callback. It should not
* be used in user code.
*/
public function getQueryBuilderPartsForCachingHash($queryBuilder)
{
return false;
}
public function __construct(ManagerRegistry $registry)
{
$this->registry = $registry;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
if ($options['multiple']) {
$builder
->addEventSubscriber(new MergeDoctrineCollectionListener())
->addViewTransformer(new CollectionToArrayTransformer(), true)
;
}
}
public function configureOptions(OptionsResolver $resolver)
{
$choiceLoader = function (Options $options) {
// Unless the choices are given explicitly, load them on demand
if (null === $options['choices']) {
$hash = null;
$qbParts = null;
// If there is no QueryBuilder we can safely cache DoctrineChoiceLoader,
// also if concrete Type can return important QueryBuilder parts to generate
// hash key we go for it as well
if (!$options['query_builder'] || false !== ($qbParts = $this->getQueryBuilderPartsForCachingHash($options['query_builder']))) {
$hash = CachingFactoryDecorator::generateHash([
$options['em'],
$options['class'],
$qbParts,
]);
if (isset($this->choiceLoaders[$hash])) {
return $this->choiceLoaders[$hash];
}
}
if (null !== $options['query_builder']) {
$entityLoader = $this->getLoader($options['em'], $options['query_builder'], $options['class']);
} else {
$queryBuilder = $options['em']->getRepository($options['class'])->createQueryBuilder('e');
$entityLoader = $this->getLoader($options['em'], $queryBuilder, $options['class']);
}
$doctrineChoiceLoader = new DoctrineChoiceLoader(
$options['em'],
$options['class'],
$options['id_reader'],
$entityLoader
);
if (null !== $hash) {
$this->choiceLoaders[$hash] = $doctrineChoiceLoader;
}
return $doctrineChoiceLoader;
}
};
$choiceName = function (Options $options) {
/** @var IdReader $idReader */
$idReader = $options['id_reader'];
// If the object has a single-column, numeric ID, use that ID as
// field name. We can only use numeric IDs as names, as we cannot
// guarantee that a non-numeric ID contains a valid form name
if ($idReader->isIntId()) {
return [__CLASS__, 'createChoiceName'];
}
// Otherwise, an incrementing integer is used as name automatically
};
// The choices are always indexed by ID (see "choices" normalizer
// and DoctrineChoiceLoader), unless the ID is composite. Then they
// are indexed by an incrementing integer.
// Use the ID/incrementing integer as choice value.
$choiceValue = function (Options $options) {
/** @var IdReader $idReader */
$idReader = $options['id_reader'];
// If the entity has a single-column ID, use that ID as value
if ($idReader->isSingleId()) {
return [$idReader, 'getIdValue'];
}
// Otherwise, an incrementing integer is used as value automatically
};
$emNormalizer = function (Options $options, $em) {
/* @var ManagerRegistry $registry */
if (null !== $em) {
if ($em instanceof ObjectManager) {
return $em;
}
return $this->registry->getManager($em);
}
$em = $this->registry->getManagerForClass($options['class']);
if (null === $em) {
throw new RuntimeException(sprintf('Class "%s" seems not to be a managed Doctrine entity. Did you forget to map it?', $options['class']));
}
return $em;
};
// Invoke the query builder closure so that we can cache choice lists
// for equal query builders
$queryBuilderNormalizer = function (Options $options, $queryBuilder) {
if (\is_callable($queryBuilder)) {
$queryBuilder = $queryBuilder($options['em']->getRepository($options['class']));
}
return $queryBuilder;
};
// Set the "id_reader" option via the normalizer. This option is not
// supposed to be set by the user.
$idReaderNormalizer = function (Options $options) {
$hash = CachingFactoryDecorator::generateHash([
$options['em'],
$options['class'],
]);
// The ID reader is a utility that is needed to read the object IDs
// when generating the field values. The callback generating the
// field values has no access to the object manager or the class
// of the field, so we store that information in the reader.
// The reader is cached so that two choice lists for the same class
// (and hence with the same reader) can successfully be cached.
if (!isset($this->idReaders[$hash])) {
$classMetadata = $options['em']->getClassMetadata($options['class']);
$this->idReaders[$hash] = new IdReader($options['em'], $classMetadata);
}
return $this->idReaders[$hash];
};
$resolver->setDefaults([
'em' => null,
'query_builder' => null,
'choices' => null,
'choice_loader' => $choiceLoader,
'choice_label' => [__CLASS__, 'createChoiceLabel'],
'choice_name' => $choiceName,
'choice_value' => $choiceValue,
'id_reader' => null, // internal
'choice_translation_domain' => false,
]);
$resolver->setRequired(['class']);
$resolver->setNormalizer('em', $emNormalizer);
$resolver->setNormalizer('query_builder', $queryBuilderNormalizer);
$resolver->setNormalizer('id_reader', $idReaderNormalizer);
$resolver->setAllowedTypes('em', ['null', 'string', 'Doctrine\Common\Persistence\ObjectManager']);
}
/**
* Return the default loader object.
*
* @param ObjectManager $manager
* @param mixed $queryBuilder
* @param string $class
*
* @return EntityLoaderInterface
*/
abstract public function getLoader(ObjectManager $manager, $queryBuilder, $class);
public function getParent()
{
return 'Symfony\Component\Form\Extension\Core\Type\ChoiceType';
}
public function reset()
{
$this->choiceLoaders = [];
}
}

View File

@ -0,0 +1,96 @@
<?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\Doctrine\Form\Type;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\ORM\Query\Parameter;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\ChoiceList\ORMQueryBuilderLoader;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;
class EntityType extends DoctrineType
{
public function configureOptions(OptionsResolver $resolver)
{
parent::configureOptions($resolver);
// Invoke the query builder closure so that we can cache choice lists
// for equal query builders
$queryBuilderNormalizer = function (Options $options, $queryBuilder) {
if (\is_callable($queryBuilder)) {
$queryBuilder = $queryBuilder($options['em']->getRepository($options['class']));
if (null !== $queryBuilder && !$queryBuilder instanceof QueryBuilder) {
throw new UnexpectedTypeException($queryBuilder, 'Doctrine\ORM\QueryBuilder');
}
}
return $queryBuilder;
};
$resolver->setNormalizer('query_builder', $queryBuilderNormalizer);
$resolver->setAllowedTypes('query_builder', ['null', 'callable', 'Doctrine\ORM\QueryBuilder']);
}
/**
* Return the default loader object.
*
* @param ObjectManager $manager
* @param QueryBuilder $queryBuilder
* @param string $class
*
* @return ORMQueryBuilderLoader
*/
public function getLoader(ObjectManager $manager, $queryBuilder, $class)
{
return new ORMQueryBuilderLoader($queryBuilder);
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'entity';
}
/**
* We consider two query builders with an equal SQL string and
* equal parameters to be equal.
*
* @param QueryBuilder $queryBuilder
*
* @return array
*
* @internal This method is public to be usable as callback. It should not
* be used in user code.
*/
public function getQueryBuilderPartsForCachingHash($queryBuilder)
{
return [
$queryBuilder->getQuery()->getSQL(),
array_map([$this, 'parameterToArray'], $queryBuilder->getParameters()->toArray()),
];
}
/**
* Converts a query parameter to an array.
*
* @return array The array representation of the parameter
*/
private function parameterToArray(Parameter $parameter)
{
return [$parameter->getName(), $parameter->getType(), $parameter->getValue()];
}
}

View File

@ -0,0 +1,19 @@
Copyright (c) 2004-2019 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -0,0 +1,98 @@
<?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\Doctrine\Logger;
use Doctrine\DBAL\Logging\SQLLogger;
use Psr\Log\LoggerInterface;
use Symfony\Component\Stopwatch\Stopwatch;
/**
* @author Fabien Potencier <fabien@symfony.com>
*/
class DbalLogger implements SQLLogger
{
const MAX_STRING_LENGTH = 32;
const BINARY_DATA_VALUE = '(binary value)';
protected $logger;
protected $stopwatch;
public function __construct(LoggerInterface $logger = null, Stopwatch $stopwatch = null)
{
$this->logger = $logger;
$this->stopwatch = $stopwatch;
}
/**
* {@inheritdoc}
*/
public function startQuery($sql, array $params = null, array $types = null)
{
if (null !== $this->stopwatch) {
$this->stopwatch->start('doctrine', 'doctrine');
}
if (null !== $this->logger) {
$this->log($sql, null === $params ? [] : $this->normalizeParams($params));
}
}
/**
* {@inheritdoc}
*/
public function stopQuery()
{
if (null !== $this->stopwatch) {
$this->stopwatch->stop('doctrine');
}
}
/**
* Logs a message.
*
* @param string $message A message to log
* @param array $params The context
*/
protected function log($message, array $params)
{
$this->logger->debug($message, $params);
}
private function normalizeParams(array $params)
{
foreach ($params as $index => $param) {
// normalize recursively
if (\is_array($param)) {
$params[$index] = $this->normalizeParams($param);
continue;
}
if (!\is_string($params[$index])) {
continue;
}
// non utf-8 strings break json encoding
if (!preg_match('//u', $params[$index])) {
$params[$index] = self::BINARY_DATA_VALUE;
continue;
}
// detect if the too long string must be shorten
if (self::MAX_STRING_LENGTH < mb_strlen($params[$index], 'UTF-8')) {
$params[$index] = mb_substr($params[$index], 0, self::MAX_STRING_LENGTH - 6, 'UTF-8').' [...]';
continue;
}
}
return $params;
}
}

View File

@ -0,0 +1,74 @@
<?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\Doctrine;
use Doctrine\Common\Persistence\AbstractManagerRegistry;
use ProxyManager\Proxy\LazyLoadingInterface;
use Symfony\Component\DependencyInjection\Container;
/**
* References Doctrine connections and entity/document managers.
*
* @author Lukas Kahwe Smith <smith@pooteeweet.org>
*/
abstract class ManagerRegistry extends AbstractManagerRegistry
{
/**
* @var Container
*/
protected $container;
/**
* {@inheritdoc}
*/
protected function getService($name)
{
return $this->container->get($name);
}
/**
* {@inheritdoc}
*/
protected function resetService($name)
{
if (!$this->container->initialized($name)) {
return;
}
$manager = $this->container->get($name);
if (!$manager instanceof LazyLoadingInterface) {
throw new \LogicException('Resetting a non-lazy manager service is not supported. '.(interface_exists(LazyLoadingInterface::class) ? sprintf('Declare the "%s" service as lazy.', $name) : 'Try running "composer require symfony/proxy-manager-bridge".'));
}
$manager->setProxyInitializer(\Closure::bind(
function (&$wrappedInstance, LazyLoadingInterface $manager) use ($name) {
if (isset($this->normalizedIds[$normalizedId = strtolower($name)])) { // BC with DI v3.4
$name = $this->normalizedIds[$normalizedId];
}
if (isset($this->aliases[$name])) {
$name = $this->aliases[$name];
}
if (isset($this->fileMap[$name])) {
$wrappedInstance = $this->load($this->fileMap[$name]);
} else {
$method = $this->methodMap[$name] ?? 'get'.strtr($name, $this->underscoreMap).'Service'; // BC with DI v3.4
$wrappedInstance = $this->{$method}(false);
}
$manager->setProxyInitializer(null);
return true;
},
$this->container,
Container::class
));
}
}

Some files were not shown because too many files have changed in this diff Show More