Merge branch '3.1'

* 3.1:
  [travis] Don't use parallel on HHVM
  [HttpKernel] Fix RequestDataCollector starting the session
  [appveyor] Ignore STATUS_HEAP_CORRUPTION errors on Windows
  [FrameworkBundle] Skip redis cache pools test on failed connection
  Fixed forwarded request data in templates
  [Security] Fix DebugAccessDecisionManager when object is not a scalar
  Skip some tests on HHVM due to a PHPunit bug
  Use the Trusty Travis infrastructure for HHVM builds
  LdapUserProvider: add missing argument type doc
  Fixed issue with missing argument in the abstract service definition for the ldap user provider
  Add 3.1 to  PR template branch row, remove 2.3
  Improve memory efficiency
  [Console] Fix BC break introduced by #18101
  document method name changes in Voter class
  add missing hint for vote() argument type
  [#18838] add a test to avoid regressions
  bumped Symfony version to 3.1.1
  updated VERSION for 3.1.0
  updated CHANGELOG for 3.1.0

Conflicts:
	src/Symfony/Component/HttpKernel/Kernel.php
This commit is contained in:
Nicolas Grekas 2016-06-03 13:14:11 +02:00
commit 37c9c397e6
22 changed files with 176 additions and 25 deletions

View File

@ -1,6 +1,6 @@
| Q | A
| ------------- | ---
| Branch? | "master" for new features / 2.3, 2.7, 2.8 or 3.0 for fixes
| Branch? | "master" for new features / 2.7, 2.8, 3.0 or 3.1 for fixes
| Bug fix? | yes/no
| New feature? | yes/no
| BC breaks? | yes/no

View File

@ -19,7 +19,11 @@ env:
matrix:
include:
# Use the newer stack for HHVM as HHVM does not support Precise anymore since a long time and so Precise has an outdated version
- php: hhvm
sudo: required
dist: trusty
group: edge
- php: 5.5
- php: 5.6
env: deps=high
@ -37,14 +41,15 @@ services:
- redis-server
before_install:
- stty cols 120
- mkdir /tmp/slapd
- slapd -f src/Symfony/Component/Ldap/Tests/Fixtures/conf/slapd.conf -h ldap://localhost:3389 &
- PHP=$TRAVIS_PHP_VERSION
# Matrix lines for intermediate PHP versions are skipped for pull requests
- if [[ ! $deps && ! $PHP = ${MIN_PHP%.*} && $PHP != hhvm && $TRAVIS_PULL_REQUEST != false ]]; then deps=skip; skip=1; fi
- if [[ ! $deps && ! $PHP = ${MIN_PHP%.*} && ! $PHP = hhvm* && $TRAVIS_PULL_REQUEST != false ]]; then deps=skip; skip=1; fi
# A sigchild-enabled-PHP is used to test the Process component on the lowest PHP matrix line
- if [[ ! $deps && $PHP = ${MIN_PHP%.*} && ! -d php-$MIN_PHP/sapi ]]; then wget http://museum.php.net/php5/php-$MIN_PHP.tar.bz2 -O - | tar -xj; (cd php-$MIN_PHP; ./configure --enable-sigchild --enable-pcntl; make -j2); fi
- if [[ $PHP != hhvm ]]; then INI_FILE=~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini; else INI_FILE=/etc/hhvm/php.ini; fi
- if [[ ! $PHP = hhvm* ]]; then INI_FILE=~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini; else INI_FILE=/etc/hhvm/php.ini; fi
- if [[ ! $skip ]]; then echo memory_limit = -1 >> $INI_FILE; fi
- if [[ ! $skip ]]; then echo session.gc_probability = 0 >> $INI_FILE; fi
- if [[ ! $skip && $PHP = 5.* ]]; then echo extension = mongo.so >> $INI_FILE; fi
@ -53,9 +58,9 @@ before_install:
- if [[ ! $skip && $PHP = 7.* ]]; then (echo yes | pecl install -f apcu-5.1.2 && echo apc.enable_cli = 1 >> $INI_FILE); fi
- if [[ ! $deps && $PHP = 5.* ]]; then (cd src/Symfony/Component/Debug/Resources/ext && phpize && ./configure && make && echo extension = $(pwd)/modules/symfony_debug.so >> $INI_FILE); fi
- if [[ ! $skip && $PHP = 5.* ]]; then pecl install -f memcached-2.1.0; fi
- if [[ ! $skip && $PHP != hhvm ]]; then echo extension = ldap.so >> $INI_FILE; fi
- if [[ ! $skip && $PHP != hhvm ]]; then echo extension = redis.so >> $INI_FILE; fi;
- if [[ ! $skip && $PHP != hhvm ]]; then phpenv config-rm xdebug.ini; fi
- if [[ ! $skip && ! $PHP = hhvm* ]]; then echo extension = ldap.so >> $INI_FILE; fi
- if [[ ! $skip && ! $PHP = hhvm* ]]; then echo extension = redis.so >> $INI_FILE; fi;
- if [[ ! $skip && ! $PHP = hhvm* ]]; then phpenv config-rm xdebug.ini; fi
- if [[ ! $skip ]]; then composer self-update --stable; fi
- if [[ ! $skip ]]; then cp .composer/* ~/.composer/; fi
- if [[ ! $skip ]]; then ./phpunit install; fi
@ -75,12 +80,13 @@ install:
- export COMPOSER_ROOT_VERSION=$SYMFONY_VERSION.x-dev
- if [[ ! $deps ]]; then composer update; else export SYMFONY_DEPRECATIONS_HELPER=weak; fi
- if [[ $TRAVIS_BRANCH = master ]]; then export SYMFONY_PHPUNIT_OVERLOAD=1; fi
- if [[ $PHP != hhvm ]]; then php -i; else hhvm --php -r 'print_r($_SERVER);print_r(ini_get_all());'; fi
- if [[ ! $PHP = hhvm* ]]; then php -i; else hhvm --php -r 'print_r($_SERVER);print_r(ini_get_all());'; fi
script:
- if [[ $skip ]]; then echo -e "\\n\\e[1;34mIntermediate PHP version $PHP is skipped for pull requests.\\e[0m"; fi
- if [[ ! $deps ]]; then echo "$COMPONENTS" | parallel --gnu '$PHPUNIT --exclude-group tty,benchmark,intl-data {}'; fi
- if [[ ! $deps ]]; then echo -e "\\nRunning tests requiring tty"; $PHPUNIT --group tty; fi
- if [[ ! $deps && ! $PHP = hhvm* ]]; then echo "$COMPONENTS" | parallel --gnu '$PHPUNIT --exclude-group tty,benchmark,intl-data {}'; fi
- if [[ ! $deps && ! $PHP = hhvm* ]]; then echo -e "\\nRunning tests requiring tty"; $PHPUNIT --group tty; fi
- if [[ ! $deps && $PHP = hhvm* ]]; then $PHPUNIT --exclude-group benchmark,intl-data; fi
- if [[ ! $deps && $PHP = ${MIN_PHP%.*} ]]; then echo -e "1\\n0" | xargs -I{} sh -c 'echo "\\nPHP --enable-sigchild enhanced={}" && ENHANCE_SIGCHLD={} php-$MIN_PHP/sapi/cli/php .phpunit/phpunit-4.8/phpunit --colors=always src/Symfony/Component/Process/'; fi
- if [[ $deps = high ]]; then echo "$COMPONENTS" | parallel --gnu -j10% 'cd {}; composer update --no-progress --ansi; $PHPUNIT --exclude-group tty,benchmark,intl-data'$LEGACY; fi
- if [[ $deps = low ]]; then echo "$COMPONENTS" | parallel --gnu -j10% 'cd {}; composer update --no-progress --ansi --prefer-lowest --prefer-stable; $PHPUNIT --exclude-group tty,benchmark,intl-data'; fi

View File

@ -7,6 +7,12 @@ in 3.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/v3.1.0...v3.1.1
* 3.1.0 (2016-05-30)
* bug #18889 [Console] SymfonyStyle: Fix alignment/prefixing of multi-line comments (chalasr)
* bug #18907 [Routing] Fix the annotation loader taking a class constant as a beginning of a class name (jakzal, nicolas-grekas)
* bug #18899 [Yaml] search for colons in strings only (xabbuh)
* 3.1.0-RC1 (2016-05-26)
* bug #18879 [Console] SymfonyStyle: Align multi-line/very-long-line blocks (chalasr)

View File

@ -1042,6 +1042,9 @@ UPGRADE FROM 2.x to 3.0
introduced in 2.8, and move your voting logic to the to the `supports($attribute, $subject)`
and `voteOnAttribute($attribute, $object, TokenInterface $token)` methods.
* The `vote()` method from the `VoterInterface` was changed to now accept arbitrary
types, and not only objects.
* The `supportsClass` and `supportsAttribute` methods were
removed from the `VoterInterface` interface.
@ -1083,7 +1086,7 @@ UPGRADE FROM 2.x to 3.0
}
```
* The `AbstractVoter::isGranted()` method have been replaced by `AbstractVoter::voteOnAttribute()`.
* The `AbstractVoter::isGranted()` method has been replaced by `Voter::voteOnAttribute()`.
Before:
@ -1102,7 +1105,7 @@ UPGRADE FROM 2.x to 3.0
After:
```php
class MyVoter extends AbstractVoter
class MyVoter extends Voter
{
protected function voteOnAttribute($attribute, $object, TokenInterface $token)
{
@ -1113,8 +1116,8 @@ UPGRADE FROM 2.x to 3.0
}
```
* The `supportsAttribute()` and `supportsClass()` methods of classes `AuthenticatedVoter`, `ExpressionVoter`
and `RoleVoter` have been removed.
* The `supportsAttribute()` and `supportsClass()` methods of the `AuthenticatedVoter`, `ExpressionVoter`,
and `RoleVoter` classes have been removed.
* The `intention` option was renamed to `csrf_token_id` for all the authentication listeners.

10
phpunit
View File

@ -53,6 +53,9 @@ if (!file_exists("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit") || md5_file(__
chdir("phpunit-$PHPUNIT_VERSION");
passthru("$COMPOSER remove --no-update phpspec/prophecy");
passthru("$COMPOSER remove --no-update symfony/yaml");
if (5.1 <= $PHPUNIT_VERSION && $PHPUNIT_VERSION < 5.4) {
passthru("$COMPOSER require --no-update phpunit/phpunit-mock-objects \"~3.1.0\"");
}
passthru("$COMPOSER require --dev --no-update symfony/phpunit-bridge \">=3.1@dev\"");
passthru("$COMPOSER install --prefer-dist --no-progress --ansi", $exit);
if ($exit) {
@ -170,8 +173,11 @@ if (isset($argv[1]) && 'symfony' === $argv[1]) {
unlink($file);
}
// Fail on any individual component failures but ignore STATUS_STACK_BUFFER_OVERRUN (-1073740791/0xC0000409) and STATUS_ACCESS_VIOLATION (-1073741819/0xC0000005) on Windows when APCu is enabled
if ($procStatus && ('\\' !== DIRECTORY_SEPARATOR || !extension_loaded('apcu') || !ini_get('apc.enable_cli') || (-1073740791 !== $procStatus && -1073741819 !== $procStatus))) {
// Fail on any individual component failures but ignore some error codes on Windows when APCu is enabled:
// STATUS_STACK_BUFFER_OVERRUN (-1073740791/0xC0000409)
// STATUS_ACCESS_VIOLATION (-1073741819/0xC0000005)
// STATUS_HEAP_CORRUPTION (-1073740940/0xC0000374)
if ($procStatus && ('\\' !== DIRECTORY_SEPARATOR || !extension_loaded('apcu') || !ini_get('apc.enable_cli') || !in_array($procStatus, array(-1073740791, -1073741819, -1073740940)))) {
$exit = $procStatus;
echo "\033[41mKO\033[0m $component\n\n";
} else {

View File

@ -38,7 +38,7 @@ class AddConsoleCommandPass implements CompilerPassInterface
throw new \InvalidArgumentException(sprintf('The service "%s" tagged "console.command" must be a subclass of "Symfony\\Component\\Console\\Command\\Command".', $id));
}
$container->setAlias($serviceId = 'console.command.'.strtolower(str_replace('\\', '_', $class)), $id);
$serviceIds[] = $serviceId;
$serviceIds[] = $definition->isPublic() ? $id : $serviceId;
}
$container->setParameter('console.command.ids', $serviceIds);

View File

@ -45,8 +45,9 @@ class AddConsoleCommandPassTest extends \PHPUnit_Framework_TestCase
$this->assertTrue($container->hasDefinition($alias));
}
$id = $public ? 'my-command' : 'console.command.symfony_bundle_frameworkbundle_tests_dependencyinjection_compiler_mycommand';
$this->assertTrue($container->hasParameter('console.command.ids'));
$this->assertSame(array('console.command.symfony_bundle_frameworkbundle_tests_dependencyinjection_compiler_mycommand'), $container->getParameter('console.command.ids'));
$this->assertSame(array($id), $container->getParameter('console.command.ids'));
}
public function visibilityProvider()

View File

@ -13,6 +13,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional;
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
use Symfony\Component\Cache\Adapter\RedisAdapter;
use Symfony\Component\Cache\Exception\InvalidArgumentException;
class CachePoolsTest extends WebTestCase
{
@ -33,6 +34,11 @@ class CachePoolsTest extends WebTestCase
throw $e;
}
$this->markTestSkipped($e->getMessage());
} catch (InvalidArgumentException $e) {
if (0 !== strpos($e->getMessage(), 'Redis connection failed')) {
throw $e;
}
$this->markTestSkipped($e->getMessage());
}
}

View File

@ -127,6 +127,7 @@
<argument /> <!-- default_roles -->
<argument /> <!-- uid key -->
<argument /> <!-- filter -->
<argument /> <!-- password_attribute -->
</service>
<service id="security.user.provider.chain" class="Symfony\Component\Security\Core\User\ChainUserProvider" abstract="true" public="false" />

View File

@ -13,7 +13,7 @@
{% endset %}
{% endif %}
{% if collector.forward %}
{% if collector.forward|default(false) %}
{% set forward_handler %}
{% import _self as helper %}
{{ helper.set_handler(collector.forward.controller) }}
@ -26,7 +26,7 @@
<span class="sf-toolbar-status sf-toolbar-status-{{ request_status_code_color }}">{{ collector.statuscode }}</span>
{% if collector.route %}
{% if collector.redirect %}{{ include('@WebProfiler/Icon/redirect.svg') }}{% endif %}
{% if collector.forward %}{{ include('@WebProfiler/Icon/forward.svg') }}{% endif %}
{% if collector.forward|default(false) %}{{ include('@WebProfiler/Icon/forward.svg') }}{% endif %}
<span class="sf-toolbar-label">{{ 'GET' != collector.method ? collector.method }} @</span>
<span class="sf-toolbar-value sf-toolbar-info-piece-additional">{{ collector.route }}</span>
{% endif %}

View File

@ -44,7 +44,7 @@
</dl>
{%- endif %}
{% if request_collector and request_collector.forward and request_collector.forward.controller.class is defined -%}
{% if request_collector and request_collector.forward|default(false) and request_collector.forward.controller.class is defined -%}
{%- set forward = request_collector.forward -%}
{%- set controller = forward.controller -%}
<dl class="metadata">

View File

@ -72,7 +72,7 @@ class StreamOutput extends Output
*/
protected function doWrite($message, $newline)
{
if (false === @fwrite($this->stream, $message.($newline ? PHP_EOL : ''))) {
if (false === @fwrite($this->stream, $message) || ($newline && (false === @fwrite($this->stream, PHP_EOL)))) {
// should never happen
throw new RuntimeException('Unable to write output.');
}

View File

@ -30,6 +30,10 @@ class MemcacheSessionHandlerTest extends \PHPUnit_Framework_TestCase
protected function setUp()
{
if (defined('HHVM_VERSION')) {
$this->markTestSkipped('PHPUnit_MockObject cannot mock the Memcache class on HHVM. See https://github.com/sebastianbergmann/phpunit-mock-objects/pull/289');
}
parent::setUp();
$this->memcache = $this->getMock('Memcache');
$this->storage = new MemcacheSessionHandler(

View File

@ -31,6 +31,10 @@ class MemcachedSessionHandlerTest extends \PHPUnit_Framework_TestCase
protected function setUp()
{
if (defined('HHVM_VERSION')) {
$this->markTestSkipped('PHPUnit_MockObject cannot mock the Memcached class on HHVM. See https://github.com/sebastianbergmann/phpunit-mock-objects/pull/289');
}
parent::setUp();
if (version_compare(phpversion('memcached'), '2.2.0', '>=')) {

View File

@ -135,6 +135,10 @@ class PdoSessionHandlerTest extends \PHPUnit_Framework_TestCase
public function testReadConvertsStreamToString()
{
if (defined('HHVM_VERSION')) {
$this->markTestSkipped('PHPUnit_MockObject cannot mock the PDOStatement class on HHVM. See https://github.com/sebastianbergmann/phpunit-mock-objects/pull/289');
}
$pdo = new MockPdo('pgsql');
$pdo->prepareResult = $this->getMock('PDOStatement');
@ -152,6 +156,10 @@ class PdoSessionHandlerTest extends \PHPUnit_Framework_TestCase
public function testReadLockedConvertsStreamToString()
{
if (defined('HHVM_VERSION')) {
$this->markTestSkipped('PHPUnit_MockObject cannot mock the PDOStatement class on HHVM. See https://github.com/sebastianbergmann/phpunit-mock-objects/pull/289');
}
$pdo = new MockPdo('pgsql');
$selectStmt = $this->getMock('PDOStatement');
$insertStmt = $this->getMock('PDOStatement');

View File

@ -130,7 +130,7 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
unset($this->controllers[$request]);
}
if (null !== $session) {
if (null !== $session && $session->isStarted()) {
if ($request->attributes->has('_redirected')) {
$this->data['redirect'] = $session->remove('sf_redirect');
}
@ -291,7 +291,7 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
public function onKernelResponse(FilterResponseEvent $event)
{
if (!$event->isMasterRequest() || !$event->getRequest()->hasSession()) {
if (!$event->isMasterRequest() || !$event->getRequest()->hasSession() || !$event->getRequest()->getSession()->isStarted()) {
return;
}

View File

@ -113,7 +113,7 @@ EOTXT;
$line = __LINE__ - 1;
ob_start();
$collector = null;
$collector->__destruct();
$this->assertSame("DumpDataCollectorTest.php on line {$line}:\n456\n", ob_get_clean());
}
}

View File

@ -11,7 +11,10 @@
namespace Symfony\Component\HttpKernel\Tests\DataCollector;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\HttpKernel;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\DataCollector\RequestDataCollector;
@ -52,6 +55,20 @@ class RequestDataCollectorTest extends \PHPUnit_Framework_TestCase
$this->assertSame('application/json', $c->getContentType());
}
public function testKernelResponseDoesNotStartSession()
{
$kernel = $this->getMock(HttpKernelInterface::class);
$request = new Request();
$session = new Session(new MockArraySessionStorage());
$request->setSession($session);
$response = new Response();
$c = new RequestDataCollector();
$c->onKernelResponse(new FilterResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, $response));
$this->assertFalse($session->isStarted());
}
/**
* Test various types of controller callables.
*/

View File

@ -103,7 +103,14 @@ class DebugAccessDecisionManager implements AccessDecisionManagerInterface
}
if (!is_object($object)) {
return sprintf('%s (%s)', gettype($object), $object);
if (is_bool($object)) {
return sprintf('%s (%s)', gettype($object), $object ? 'true' : 'false');
}
if (is_scalar($object)) {
return sprintf('%s (%s)', gettype($object), $object);
}
return gettype($object);
}
$objectClass = class_exists('Doctrine\Common\Util\ClassUtils') ? ClassUtils::getClass($object) : get_class($object);

View File

@ -0,0 +1,43 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Core\Tests\Authorization;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManager;
use Symfony\Component\Security\Core\Authorization\DebugAccessDecisionManager;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
class DebugAccessDecisionManagerTest extends \PHPUnit_Framework_TestCase
{
/**
* @dataProvider provideObjectsAndLogs
*/
public function testDecideLog($expectedLog, $object)
{
$adm = new DebugAccessDecisionManager(new AccessDecisionManager());
$adm->decide($this->getMock(TokenInterface::class), array('ATTRIBUTE_1'), $object);
$this->assertSame($expectedLog, $adm->getDecisionLog());
}
public function provideObjectsAndLogs()
{
$object = new \stdClass();
yield array(array(array('attributes' => array('ATTRIBUTE_1'), 'object' => 'NULL', 'result' => false)), null);
yield array(array(array('attributes' => array('ATTRIBUTE_1'), 'object' => 'boolean (true)', 'result' => false)), true);
yield array(array(array('attributes' => array('ATTRIBUTE_1'), 'object' => 'string (jolie string)', 'result' => false)), 'jolie string');
yield array(array(array('attributes' => array('ATTRIBUTE_1'), 'object' => 'integer (12345)', 'result' => false)), 12345);
yield array(array(array('attributes' => array('ATTRIBUTE_1'), 'object' => 'resource', 'result' => false)), fopen(__FILE__, 'r'));
yield array(array(array('attributes' => array('ATTRIBUTE_1'), 'object' => 'array', 'result' => false)), array());
yield array(array(array('attributes' => array('ATTRIBUTE_1'), 'object' => sprintf('stdClass (object hash: %s)', spl_object_hash($object)), 'result' => false)), $object);
}
}

View File

@ -42,6 +42,7 @@ class LdapUserProvider implements UserProviderInterface
* @param array $defaultRoles
* @param string $uidKey
* @param string $filter
* @param string $passwordAttribute
*/
public function __construct(LdapInterface $ldap, $baseDn, $searchDn = null, $searchPassword = null, array $defaultRoles = array(), $uidKey = 'sAMAccountName', $filter = '({uid_key}={username})', $passwordAttribute = null)
{

View File

@ -545,6 +545,28 @@ class ObjectNormalizerTest extends \PHPUnit_Framework_TestCase
$serializer->denormalize(array('date' => 'foo'), ObjectOuter::class);
}
public function testExtractAttributesRespectsFormat()
{
$normalizer = new FormatAndContextAwareNormalizer();
$data = new ObjectDummy();
$data->setFoo('bar');
$data->bar = 'foo';
$this->assertSame(array('foo' => 'bar', 'bar' => 'foo'), $normalizer->normalize($data, 'foo_and_bar_included'));
}
public function testExtractAttributesRespectsContext()
{
$normalizer = new FormatAndContextAwareNormalizer();
$data = new ObjectDummy();
$data->setFoo('bar');
$data->bar = 'foo';
$this->assertSame(array('foo' => 'bar', 'bar' => 'foo'), $normalizer->normalize($data, null, array('include_foo_and_bar' => true)));
}
}
class ObjectDummy
@ -744,3 +766,19 @@ class ObjectInner
public $foo;
public $bar;
}
class FormatAndContextAwareNormalizer extends ObjectNormalizer
{
protected function isAllowedAttribute($classOrObject, $attribute, $format = null, array $context = array())
{
if (in_array($attribute, array('foo', 'bar')) && 'foo_and_bar_included' === $format) {
return true;
}
if (in_array($attribute, array('foo', 'bar')) && isset($context['include_foo_and_bar']) && true === $context['include_foo_and_bar']) {
return true;
}
return false;
}
}