Merge branch '4.2'

* 4.2:
  [VarExporter] fix dumping private properties from abstract classes
  Fix empty output for debug:autowiring when reflection-docblock is not available
  [Workflow] Fixed BC break for Workflow metadata
  [Routing] ignore trailing slash for non-GET requests
This commit is contained in:
Nicolas Grekas 2018-12-03 22:43:20 +00:00
commit c7fe1b6bcb
12 changed files with 45 additions and 25 deletions

View File

@ -292,7 +292,7 @@ abstract class Descriptor implements DescriptorInterface
*/
public static function getClassDescription(string $class, string &$resolvedClass = null): string
{
$resolvedClass = null;
$resolvedClass = $class;
if (!interface_exists(DocBlockFactoryInterface::class)) {
return '';

View File

@ -547,7 +547,7 @@ class FrameworkExtension extends Extension
}
if ($transition['metadata']) {
$transitionsMetadataDefinition->addMethodCall('attach', array(
$transitionDefinition,
new Reference($transitionId),
$transition['metadata'],
));
}
@ -569,7 +569,7 @@ class FrameworkExtension extends Extension
}
if ($transition['metadata']) {
$transitionsMetadataDefinition->addMethodCall('attach', array(
$transitionDefinition,
new Reference($transitionId),
$transition['metadata'],
));
}

View File

@ -258,10 +258,8 @@ abstract class FrameworkExtensionTest extends TestCase
$this->assertSame('attach', $transitionsMetadataCall[0]);
$params = $transitionsMetadataCall[1];
$this->assertCount(2, $params);
$this->assertInstanceOf(Definition::class, $params[0]);
$this->assertSame(Workflow\Transition::class, $params[0]->getClass());
$this->assertSame(array('submit', 'start', 'travis'), $params[0]->getArguments());
$this->assertSame(array('title' => 'transition submit title'), $params[1]);
$this->assertInstanceOf(Reference::class, $params[0]);
$this->assertSame('state_machine.pull_request.transition.0', (string) $params[0]);
$serviceMarkingStoreWorkflowDefinition = $container->getDefinition('workflow.service_marking_store_workflow');
/** @var Reference $markingStoreRef */

View File

@ -90,7 +90,7 @@ trait PhpMatcherTrait
if ('/' === $pathinfo || $hasTrailingSlash === ('/' === $pathinfo[-1])) {
// no-op
} elseif ($this instanceof RedirectableUrlMatcherInterface) {
} elseif ($this instanceof RedirectableUrlMatcherInterface && (!$requiredMethods || isset($requiredMethods['GET'])) && 'GET' === $canonicalMethod) {
return $allow = $allowSchemes = array();
} else {
continue;
@ -139,7 +139,7 @@ trait PhpMatcherTrait
}
}
if ($hasTrailingSlash !== ('/' === $pathinfo[-1])) {
if ($this instanceof RedirectableUrlMatcherInterface && (!$requiredMethods || isset($requiredMethods['GET']))) {
if ($this instanceof RedirectableUrlMatcherInterface && (!$requiredMethods || isset($requiredMethods['GET'])) && 'GET' === $canonicalMethod) {
return $allow = $allowSchemes = array();
}
continue;

View File

@ -130,6 +130,10 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface
*/
protected function matchCollection($pathinfo, RouteCollection $routes)
{
// HEAD and GET are equivalent as per RFC
if ('HEAD' === $method = $this->context->getMethod()) {
$method = 'GET';
}
$supportsTrailingSlash = '/' !== $pathinfo && '' !== $pathinfo && $this instanceof RedirectableUrlMatcherInterface;
foreach ($routes as $name => $route) {
@ -140,7 +144,7 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface
// check the static prefix of the URL first. Only use the more expensive preg_match when it matches
if ('' === $staticPrefix || 0 === strpos($pathinfo, $staticPrefix)) {
// no-op
} elseif (!$supportsTrailingSlash || ($requiredMethods && !\in_array('GET', $requiredMethods))) {
} elseif (!$supportsTrailingSlash || ($requiredMethods && !\in_array('GET', $requiredMethods)) || 'GET' !== $method) {
continue;
} elseif ('/' === $staticPrefix[-1] && substr($staticPrefix, 0, -1) === $pathinfo) {
return $this->allow = $this->allowSchemes = array();
@ -170,7 +174,7 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface
}
}
if ($hasTrailingSlash !== ('/' === $pathinfo[-1])) {
if (!$requiredMethods || \in_array('GET', $requiredMethods)) {
if ((!$requiredMethods || \in_array('GET', $requiredMethods)) && 'GET' === $method) {
return $this->allow = $this->allowSchemes = array();
}
continue;
@ -190,11 +194,6 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface
$hasRequiredScheme = !$route->getSchemes() || $route->hasScheme($this->context->getScheme());
if ($requiredMethods) {
// HEAD and GET are equivalent as per RFC
if ('HEAD' === $method = $this->context->getMethod()) {
$method = 'GET';
}
if (!\in_array($method, $requiredMethods)) {
if ($hasRequiredScheme) {
$this->allow = array_merge($this->allow, $requiredMethods);

View File

@ -723,6 +723,17 @@ class UrlMatcherTest extends TestCase
'customerId' => '123',
);
$this->assertEquals($expected, $matcher->match('/api/customers/123/contactpersons'));
$coll = new RouteCollection();
$coll->add('a', new Route('/api/customers/{customerId}/contactpersons/', array(), array(), array(), '', array(), array('get')));
$coll->add('b', new Route('/api/customers/{customerId}/contactpersons', array(), array(), array(), '', array(), array('post')));
$matcher = $this->getUrlMatcher($coll, new RequestContext('', 'POST'));
$expected = array(
'_route' => 'b',
'customerId' => '123',
);
$this->assertEquals($expected, $matcher->match('/api/customers/123/contactpersons'));
}
protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null)

View File

@ -125,7 +125,8 @@ class Exporter
$c = 'stdClass';
} elseif ('*' === $n[1]) {
$n = substr($n, 3);
if ('Error' === $c = $class) {
$c = $reflector->getProperty($n)->class;
if ('Error' === $c) {
$c = 'TypeError';
} elseif ('Exception' === $c) {
$c = 'ErrorException';

View File

@ -11,6 +11,8 @@
namespace Symfony\Component\VarExporter\Internal;
use Symfony\Component\VarExporter\Exception\ClassNotFoundException;
/**
* @author Nicolas Grekas <p@tchwork.com>
*
@ -59,7 +61,10 @@ class Hydrator
};
}
$classReflector = Registry::$reflectors[$class] ?? Registry::getClassReflector($class);
if (!\class_exists($class) && !\interface_exists($class, false) && !\trait_exists($class, false)) {
throw new ClassNotFoundException($class);
}
$classReflector = new \ReflectionClass($class);
if (!$classReflector->isInternal()) {
return self::$hydrators[$class] = (self::$hydrators['stdClass'] ?? self::getHydrator('stdClass'))->bindTo(null, $class);

View File

@ -6,10 +6,13 @@ return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
],
null,
[
'Symfony\\Component\\VarExporter\\Tests\\ConcreteClass' => [
'Symfony\\Component\\VarExporter\\Tests\\AbstractClass' => [
'foo' => [
123,
],
'bar' => [
234,
],
],
],
$o[0],

View File

@ -6,7 +6,7 @@ return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
]),
null,
[
'Symfony\\Component\\VarExporter\\Tests\\FinalError' => [
'TypeError' => [
'file' => [
\dirname(__DIR__).\DIRECTORY_SEPARATOR.'VarExporterTest.php',
],

View File

@ -10,17 +10,13 @@ return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
'Symfony\\Component\\VarExporter\\Tests\\MyPrivateValue' => [
'prot' => [
123,
123,
],
'priv' => [
234,
234,
],
],
'Symfony\\Component\\VarExporter\\Tests\\MyPrivateChildValue' => [
'prot' => [
1 => 123,
],
],
],
[
$o[0],

View File

@ -326,6 +326,12 @@ final class FinalStdClass extends \stdClass
abstract class AbstractClass
{
protected $foo;
private $bar;
protected function setBar($bar)
{
$this->bar = $bar;
}
}
class ConcreteClass extends AbstractClass
@ -333,5 +339,6 @@ class ConcreteClass extends AbstractClass
public function __construct()
{
$this->foo = 123;
$this->setBar(234);
}
}