Merge branch '4.4' into 5.2

* 4.4:
  Reapply the change to allow to set the composer binary path
  [DependencyInjection] throw proper exception when decorating a synthetic service
  [WebLink] Sync type with parent interface
  [WebLink] fix types on Link::withAttribute()
  [ErrorHandler][DebugClassLoader] Do not check Phake mocks classes
This commit is contained in:
Alexander M. Turek 2021-06-22 18:06:23 +02:00
commit e85323f088
5 changed files with 38 additions and 7 deletions

View File

@ -157,12 +157,14 @@ if ('disabled' === $getEnvVar('SYMFONY_DEPRECATIONS_HELPER')) {
putenv('SYMFONY_DEPRECATIONS_HELPER=disabled');
}
$COMPOSER = file_exists($COMPOSER = $oldPwd.'/composer.phar')
|| ($COMPOSER = rtrim((string) ('\\' === \DIRECTORY_SEPARATOR ? preg_replace('/[\r\n].*/', '', `where.exe composer.phar 2> NUL`) : `which composer.phar 2> /dev/null`)))
|| ($COMPOSER = rtrim((string) ('\\' === \DIRECTORY_SEPARATOR ? preg_replace('/[\r\n].*/', '', `where.exe composer 2> NUL`) : `which composer 2> /dev/null`)))
|| file_exists($COMPOSER = rtrim((string) ('\\' === \DIRECTORY_SEPARATOR ? `git rev-parse --show-toplevel 2> NUL` : `git rev-parse --show-toplevel 2> /dev/null`)).\DIRECTORY_SEPARATOR.'composer.phar')
? ('#!/usr/bin/env php' === file_get_contents($COMPOSER, false, null, 0, 18) ? $PHP : '').' '.escapeshellarg($COMPOSER) // detect shell wrappers by looking at the shebang
: 'composer';
if (false === $COMPOSER = getenv('COMPOSER_BINARY')) {
$COMPOSER = file_exists($COMPOSER = $oldPwd.'/composer.phar')
|| ($COMPOSER = rtrim((string) ('\\' === \DIRECTORY_SEPARATOR ? preg_replace('/[\r\n].*/', '', `where.exe composer.phar 2> NUL`) : `which composer.phar 2> /dev/null`)))
|| ($COMPOSER = rtrim((string) ('\\' === \DIRECTORY_SEPARATOR ? preg_replace('/[\r\n].*/', '', `where.exe composer 2> NUL`) : `which composer 2> /dev/null`)))
|| file_exists($COMPOSER = rtrim((string) ('\\' === \DIRECTORY_SEPARATOR ? `git rev-parse --show-toplevel 2> NUL` : `git rev-parse --show-toplevel 2> /dev/null`)).\DIRECTORY_SEPARATOR.'composer.phar')
? ('#!/usr/bin/env php' === file_get_contents($COMPOSER, false, null, 0, 18) ? $PHP : '').' '.escapeshellarg($COMPOSER) // detect shell wrappers by looking at the shebang
: 'composer';
}
$prevCacheDir = getenv('COMPOSER_CACHE_DIR');
if ($prevCacheDir) {

View File

@ -14,6 +14,7 @@ namespace Symfony\Component\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use Symfony\Component\DependencyInjection\Reference;
@ -70,6 +71,7 @@ class DecoratorServicePass extends AbstractRecursivePass
$public = $alias->isPublic();
$private = $alias->isPrivate();
$container->setAlias($renamedId, new Alias((string) $alias, false));
$decoratedDefinition = $container->findDefinition($alias);
} elseif ($container->hasDefinition($inner)) {
$decoratedDefinition = $container->getDefinition($inner);
$public = $decoratedDefinition->isPublic();
@ -83,10 +85,15 @@ class DecoratorServicePass extends AbstractRecursivePass
} elseif (ContainerInterface::NULL_ON_INVALID_REFERENCE === $invalidBehavior) {
$public = $definition->isPublic();
$private = $definition->isPrivate();
$decoratedDefinition = null;
} else {
throw new ServiceNotFoundException($inner, $id);
}
if ($decoratedDefinition && $decoratedDefinition->isSynthetic()) {
throw new InvalidArgumentException(sprintf('A synthetic service cannot be decorated: service "%s" cannot decorate "%s".', $id, $inner));
}
if (isset($decoratingDefinitions[$inner])) {
$decoratingDefinition = $decoratingDefinitions[$inner];

View File

@ -16,6 +16,7 @@ use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\Compiler\DecoratorServicePass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use Symfony\Component\DependencyInjection\Reference;
@ -261,6 +262,23 @@ class DecoratorServicePassTest extends TestCase
$this->assertEquals(['bar' => ['attr' => 'baz'], 'foobar' => ['attr' => 'bar']], $container->getDefinition('baz')->getTags());
}
public function testCannotDecorateSyntheticService()
{
$container = new ContainerBuilder();
$container
->register('foo')
->setSynthetic(true)
;
$container
->register('baz')
->setDecoratedService('foo')
;
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('A synthetic service cannot be decorated: service "baz" cannot decorate "foo".');
$this->process($container);
}
public function testGenericInnerReference()
{
$container = new ContainerBuilder();

View File

@ -15,6 +15,7 @@ use Composer\InstalledVersions;
use Doctrine\Common\Persistence\Proxy as LegacyProxy;
use Doctrine\Persistence\Proxy;
use Mockery\MockInterface;
use Phake\IMock;
use PHPUnit\Framework\MockObject\Matcher\StatelessInvocation;
use PHPUnit\Framework\MockObject\MockObject;
use Prophecy\Prophecy\ProphecySubjectInterface;
@ -310,6 +311,7 @@ class DebugClassLoader
&& !is_subclass_of($symbols[$i], ProxyInterface::class)
&& !is_subclass_of($symbols[$i], LegacyProxy::class)
&& !is_subclass_of($symbols[$i], MockInterface::class)
&& !is_subclass_of($symbols[$i], IMock::class)
) {
$loader->checkClass($symbols[$i]);
}

View File

@ -46,7 +46,7 @@ class Link implements EvolvableLinkInterface
private $rel = [];
/**
* @var string[]
* @var array<string, string|bool|string[]>
*/
private $attributes = [];
@ -132,6 +132,8 @@ class Link implements EvolvableLinkInterface
/**
* {@inheritdoc}
*
* @param string|\Stringable|int|float|bool|string[] $value
*
* @return static
*/
public function withAttribute($attribute, $value)