Merge branch '3.4'
* 3.4: [Bridge/PhpUnit] Sync the bridge version installed in vendor/ and in phpunit clone [DI] Analyze setter-circular deps more precisely fixing that PropertyNormalizer supports parent properties [SecurityBundle] Don't trigger auto-picking notice if provider is set per listener [TwigBundle][FrameworkBundle] Remove the internals from debug autowiring [DI] Skip hot_path tag for deprecated services as their class might also be [Cache] Memcached options should ignore "lazy" [FrameworkBundle] Dont create empty bundles directory
This commit is contained in:
commit
5b6c1b3132
@ -68,7 +68,17 @@ if (!file_exists("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit") || md5_file(__
|
||||
if (5.1 <= $PHPUNIT_VERSION && $PHPUNIT_VERSION < 5.4) {
|
||||
passthru("$COMPOSER require --no-update phpunit/phpunit-mock-objects \"~3.1.0\"");
|
||||
}
|
||||
passthru("$COMPOSER require --no-update symfony/phpunit-bridge \"~3.4-beta5@dev|^4.0-beta5@dev\"");
|
||||
passthru("$COMPOSER require --no-update symfony/phpunit-bridge \"*\"");
|
||||
if (file_exists(($path = dirname(__DIR__)).'/composer.json')) {
|
||||
if (file_exists($path.'/vendor/symfony/phpunit-bridge/composer.json')) {
|
||||
$path .= '/vendor/symfony/phpunit-bridge';
|
||||
}
|
||||
} elseif (file_exists($path.'/symfony/phpunit-bridge/composer.json')) {
|
||||
$path .= '/symfony/phpunit-bridge';
|
||||
}
|
||||
if (file_exists($path)) {
|
||||
passthru("$COMPOSER config repositories.phpunit-bridge path ".escapeshellarg($path));
|
||||
}
|
||||
$prevRoot = getenv('COMPOSER_ROOT_VERSION');
|
||||
putenv("COMPOSER_ROOT_VERSION=$PHPUNIT_VERSION.99");
|
||||
$exit = proc_close(proc_open("$COMPOSER install --no-dev --prefer-dist --no-progress --ansi", array(), $p, getcwd(), null, array('bypass_shell' => true)));
|
||||
|
@ -98,9 +98,7 @@ EOT
|
||||
}
|
||||
}
|
||||
|
||||
// Create the bundles directory otherwise symlink will fail.
|
||||
$bundlesDir = $targetArg.'/bundles/';
|
||||
$this->filesystem->mkdir($bundlesDir, 0777);
|
||||
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
$io->newLine();
|
||||
@ -164,10 +162,14 @@ EOT
|
||||
}
|
||||
}
|
||||
// remove the assets of the bundles that no longer exist
|
||||
$dirsToRemove = Finder::create()->depth(0)->directories()->exclude($validAssetDirs)->in($bundlesDir);
|
||||
$this->filesystem->remove($dirsToRemove);
|
||||
if (is_dir($bundlesDir)) {
|
||||
$dirsToRemove = Finder::create()->depth(0)->directories()->exclude($validAssetDirs)->in($bundlesDir);
|
||||
$this->filesystem->remove($dirsToRemove);
|
||||
}
|
||||
|
||||
$io->table(array('', 'Bundle', 'Method / Error'), $rows);
|
||||
if ($rows) {
|
||||
$io->table(array('', 'Bundle', 'Method / Error'), $rows);
|
||||
}
|
||||
|
||||
if (0 !== $exitCode) {
|
||||
$io->error('Some errors occurred while installing assets.');
|
||||
@ -175,7 +177,7 @@ EOT
|
||||
if ($copyUsed) {
|
||||
$io->note('Some assets were installed via copy. If you make changes to these assets you have to run this command again.');
|
||||
}
|
||||
$io->success('All assets were successfully installed.');
|
||||
$io->success($rows ? 'All assets were successfully installed.' : 'No assets were provided by any bundle.');
|
||||
}
|
||||
|
||||
return $exitCode;
|
||||
|
@ -13,13 +13,6 @@ namespace Symfony\Bundle\FrameworkBundle\DependencyInjection;
|
||||
|
||||
use Doctrine\Common\Annotations\Reader;
|
||||
use Symfony\Bridge\Monolog\Processor\DebugProcessor;
|
||||
use Symfony\Bundle\FrameworkBundle\Command\RouterDebugCommand;
|
||||
use Symfony\Bundle\FrameworkBundle\Command\RouterMatchCommand;
|
||||
use Symfony\Bundle\FrameworkBundle\Command\TranslationDebugCommand;
|
||||
use Symfony\Bundle\FrameworkBundle\Command\TranslationUpdateCommand;
|
||||
use Symfony\Bundle\FrameworkBundle\Command\WorkflowDumpCommand;
|
||||
use Symfony\Bundle\FrameworkBundle\Command\XliffLintCommand;
|
||||
use Symfony\Bundle\FrameworkBundle\Command\YamlLintCommand;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||
use Symfony\Bundle\FrameworkBundle\Routing\AnnotatedRouteControllerLoader;
|
||||
@ -120,10 +113,10 @@ class FrameworkExtension extends Extension
|
||||
$loader->load('console.xml');
|
||||
|
||||
if (!class_exists(BaseXliffLintCommand::class)) {
|
||||
$container->removeDefinition(XliffLintCommand::class);
|
||||
$container->removeDefinition('console.command.xliff_lint');
|
||||
}
|
||||
if (!class_exists(BaseYamlLintCommand::class)) {
|
||||
$container->removeDefinition(YamlLintCommand::class);
|
||||
$container->removeDefinition('console.command.yaml_lint');
|
||||
}
|
||||
}
|
||||
|
||||
@ -203,7 +196,7 @@ class FrameworkExtension extends Extension
|
||||
$container->removeDefinition('form.type_guesser.validator');
|
||||
}
|
||||
} else {
|
||||
$container->removeDefinition('Symfony\Component\Form\Command\DebugCommand');
|
||||
$container->removeDefinition('console.command.form_debug');
|
||||
}
|
||||
|
||||
$this->registerSecurityCsrfConfiguration($config['csrf_protection'], $container, $loader);
|
||||
@ -431,7 +424,7 @@ class FrameworkExtension extends Extension
|
||||
private function registerWorkflowConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
|
||||
{
|
||||
if (!$config['enabled']) {
|
||||
$container->removeDefinition(WorkflowDumpCommand::class);
|
||||
$container->removeDefinition('console.command.workflow_dump');
|
||||
|
||||
return;
|
||||
}
|
||||
@ -603,8 +596,8 @@ class FrameworkExtension extends Extension
|
||||
private function registerRouterConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
|
||||
{
|
||||
if (!$this->isConfigEnabled($container, $config)) {
|
||||
$container->removeDefinition(RouterDebugCommand::class);
|
||||
$container->removeDefinition(RouterMatchCommand::class);
|
||||
$container->removeDefinition('console.command.router_debug');
|
||||
$container->removeDefinition('console.command.router_match');
|
||||
|
||||
return;
|
||||
}
|
||||
@ -857,8 +850,8 @@ class FrameworkExtension extends Extension
|
||||
private function registerTranslatorConfiguration(array $config, ContainerBuilder $container, LoaderInterface $loader)
|
||||
{
|
||||
if (!$this->isConfigEnabled($container, $config)) {
|
||||
$container->removeDefinition(TranslationDebugCommand::class);
|
||||
$container->removeDefinition(TranslationUpdateCommand::class);
|
||||
$container->removeDefinition('console.command.translation_debug');
|
||||
$container->removeDefinition('console.command.translation_update');
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -13,75 +13,75 @@
|
||||
<tag name="monolog.logger" channel="console" />
|
||||
</service>
|
||||
|
||||
<service id="Symfony\Bundle\FrameworkBundle\Command\AboutCommand">
|
||||
<service id="console.command.about" class="Symfony\Bundle\FrameworkBundle\Command\AboutCommand">
|
||||
<tag name="console.command" command="about" />
|
||||
</service>
|
||||
|
||||
<service id="Symfony\Bundle\FrameworkBundle\Command\AssetsInstallCommand">
|
||||
<service id="console.command.assets_install" class="Symfony\Bundle\FrameworkBundle\Command\AssetsInstallCommand">
|
||||
<argument type="service" id="filesystem" />
|
||||
<tag name="console.command" command="assets:install" />
|
||||
</service>
|
||||
|
||||
<service id="Symfony\Bundle\FrameworkBundle\Command\CacheClearCommand">
|
||||
<service id="console.command.cache_clear" class="Symfony\Bundle\FrameworkBundle\Command\CacheClearCommand">
|
||||
<argument type="service" id="cache_clearer" />
|
||||
<argument type="service" id="filesystem" />
|
||||
<tag name="console.command" command="cache:clear" />
|
||||
</service>
|
||||
|
||||
<service id="Symfony\Bundle\FrameworkBundle\Command\CachePoolClearCommand">
|
||||
<service id="console.command.cache_pool_clear" class="Symfony\Bundle\FrameworkBundle\Command\CachePoolClearCommand">
|
||||
<argument type="service" id="cache.global_clearer" />
|
||||
<tag name="console.command" command="cache:pool:clear" />
|
||||
</service>
|
||||
|
||||
<service id="Symfony\Bundle\FrameworkBundle\Command\CachePoolPruneCommand">
|
||||
<service id="console.command.cache_pool_prune" class="Symfony\Bundle\FrameworkBundle\Command\CachePoolPruneCommand">
|
||||
<argument type="iterator" />
|
||||
<tag name="console.command" command="cache:pool:prune" />
|
||||
</service>
|
||||
|
||||
<service id="Symfony\Bundle\FrameworkBundle\Command\CacheWarmupCommand">
|
||||
<service id="console.command.cache_warmup" class="Symfony\Bundle\FrameworkBundle\Command\CacheWarmupCommand">
|
||||
<argument type="service" id="cache_warmer" />
|
||||
<tag name="console.command" command="cache:warmup" />
|
||||
</service>
|
||||
|
||||
<service id="Symfony\Bundle\FrameworkBundle\Command\ConfigDebugCommand">
|
||||
<service id="console.command.config_debug" class="Symfony\Bundle\FrameworkBundle\Command\ConfigDebugCommand">
|
||||
<tag name="console.command" command="debug:config" />
|
||||
</service>
|
||||
|
||||
<service id="Symfony\Bundle\FrameworkBundle\Command\ConfigDumpReferenceCommand">
|
||||
<service id="console.command.config_dump_reference" class="Symfony\Bundle\FrameworkBundle\Command\ConfigDumpReferenceCommand">
|
||||
<tag name="console.command" command="config:dump-reference" />
|
||||
</service>
|
||||
|
||||
<service id="Symfony\Bundle\FrameworkBundle\Command\ContainerDebugCommand">
|
||||
<service id="console.command.container_debug" class="Symfony\Bundle\FrameworkBundle\Command\ContainerDebugCommand">
|
||||
<tag name="console.command" command="debug:container" />
|
||||
</service>
|
||||
|
||||
<service id="Symfony\Bundle\FrameworkBundle\Command\DebugAutowiringCommand">
|
||||
<service id="console.command.debug_autowiring" class="Symfony\Bundle\FrameworkBundle\Command\DebugAutowiringCommand">
|
||||
<tag name="console.command" command="debug:autowiring" />
|
||||
</service>
|
||||
|
||||
<service id="Symfony\Bundle\FrameworkBundle\Command\EventDispatcherDebugCommand">
|
||||
<service id="console.command.event_dispatcher_debug" class="Symfony\Bundle\FrameworkBundle\Command\EventDispatcherDebugCommand">
|
||||
<argument type="service" id="event_dispatcher" />
|
||||
<tag name="console.command" command="debug:event-dispatcher" />
|
||||
</service>
|
||||
|
||||
<service id="Symfony\Bundle\FrameworkBundle\Command\RouterDebugCommand">
|
||||
<service id="console.command.router_debug" class="Symfony\Bundle\FrameworkBundle\Command\RouterDebugCommand">
|
||||
<argument type="service" id="router" />
|
||||
<tag name="console.command" command="debug:router" />
|
||||
</service>
|
||||
|
||||
<service id="Symfony\Bundle\FrameworkBundle\Command\RouterMatchCommand">
|
||||
<service id="console.command.router_match" class="Symfony\Bundle\FrameworkBundle\Command\RouterMatchCommand">
|
||||
<argument type="service" id="router" />
|
||||
<tag name="console.command" command="router:match" />
|
||||
</service>
|
||||
|
||||
<service id="Symfony\Bundle\FrameworkBundle\Command\TranslationDebugCommand">
|
||||
<service id="console.command.translation_debug" class="Symfony\Bundle\FrameworkBundle\Command\TranslationDebugCommand">
|
||||
<argument type="service" id="translator" />
|
||||
<argument type="service" id="translation.reader" />
|
||||
<argument type="service" id="translation.extractor" />
|
||||
<tag name="console.command" command="debug:translation" />
|
||||
</service>
|
||||
|
||||
<service id="Symfony\Bundle\FrameworkBundle\Command\TranslationUpdateCommand">
|
||||
<service id="console.command.translation_update" class="Symfony\Bundle\FrameworkBundle\Command\TranslationUpdateCommand">
|
||||
<argument type="service" id="translation.writer" />
|
||||
<argument type="service" id="translation.reader" />
|
||||
<argument type="service" id="translation.extractor" />
|
||||
@ -89,19 +89,19 @@
|
||||
<tag name="console.command" command="translation:update" />
|
||||
</service>
|
||||
|
||||
<service id="Symfony\Bundle\FrameworkBundle\Command\WorkflowDumpCommand">
|
||||
<service id="console.command.workflow_dump" class="Symfony\Bundle\FrameworkBundle\Command\WorkflowDumpCommand">
|
||||
<tag name="console.command" command="workflow:dump" />
|
||||
</service>
|
||||
|
||||
<service id="Symfony\Bundle\FrameworkBundle\Command\XliffLintCommand">
|
||||
<service id="console.command.xliff_lint" class="Symfony\Bundle\FrameworkBundle\Command\XliffLintCommand">
|
||||
<tag name="console.command" command="lint:xliff" />
|
||||
</service>
|
||||
|
||||
<service id="Symfony\Bundle\FrameworkBundle\Command\YamlLintCommand">
|
||||
<service id="console.command.yaml_lint" class="Symfony\Bundle\FrameworkBundle\Command\YamlLintCommand">
|
||||
<tag name="console.command" command="lint:yaml" />
|
||||
</service>
|
||||
|
||||
<service id="Symfony\Component\Form\Command\DebugCommand">
|
||||
<service id="console.command.form_debug" class="Symfony\Component\Form\Command\DebugCommand">
|
||||
<argument type="service" id="form.registry" />
|
||||
<argument type="collection" /> <!-- All form types namespaces are stored here by FormPass -->
|
||||
<argument type="collection" /> <!-- All services form types are stored here by FormPass -->
|
||||
|
@ -55,12 +55,12 @@
|
||||
<argument type="tagged" tag="config_cache.resource_checker" />
|
||||
</service>
|
||||
|
||||
<service id="Symfony\Component\DependencyInjection\Config\ContainerParametersResourceChecker">
|
||||
<service id="dependency_injection.config.container_parameters_resource_checker" class="Symfony\Component\DependencyInjection\Config\ContainerParametersResourceChecker">
|
||||
<argument type="service" id="service_container" />
|
||||
<tag name="config_cache.resource_checker" priority="-980" />
|
||||
</service>
|
||||
|
||||
<service id="Symfony\Component\Config\Resource\SelfCheckingResourceChecker">
|
||||
<service id="config.resource.self_checking_resource_checker" class="Symfony\Component\Config\Resource\SelfCheckingResourceChecker">
|
||||
<tag name="config_cache.resource_checker" priority="-990" />
|
||||
</service>
|
||||
|
||||
|
@ -12,7 +12,6 @@
|
||||
namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection;
|
||||
|
||||
use Doctrine\Common\Annotations\Annotation;
|
||||
use Symfony\Bundle\FrameworkBundle\Command\WorkflowDumpCommand;
|
||||
use Symfony\Bundle\FullStack;
|
||||
use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
|
||||
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddAnnotationsCachedReaderPass;
|
||||
@ -307,7 +306,7 @@ abstract class FrameworkExtensionTest extends TestCase
|
||||
$container = $this->createContainerFromFile('workflows_enabled');
|
||||
|
||||
$this->assertTrue($container->has(Registry::class));
|
||||
$this->assertTrue($container->hasDefinition(WorkflowDumpCommand::class));
|
||||
$this->assertTrue($container->hasDefinition('console.command.workflow_dump'));
|
||||
}
|
||||
|
||||
public function testRouter()
|
||||
|
@ -11,7 +11,6 @@
|
||||
|
||||
namespace Symfony\Bundle\SecurityBundle\DependencyInjection;
|
||||
|
||||
use Symfony\Bundle\SecurityBundle\Command\UserPasswordEncoderCommand;
|
||||
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\SecurityFactoryInterface;
|
||||
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider\UserProviderFactoryInterface;
|
||||
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
|
||||
@ -109,7 +108,7 @@ class SecurityExtension extends Extension
|
||||
|
||||
if (class_exists(Application::class)) {
|
||||
$loader->load('console.xml');
|
||||
$container->getDefinition(UserPasswordEncoderCommand::class)->replaceArgument(1, array_keys($config['encoders']));
|
||||
$container->getDefinition('security.command.user_password_encoder')->replaceArgument(1, array_keys($config['encoders']));
|
||||
}
|
||||
|
||||
$container->registerForAutoconfiguration(VoterInterface::class)
|
||||
@ -245,17 +244,16 @@ class SecurityExtension extends Extension
|
||||
$config->replaceArgument(4, $firewall['stateless']);
|
||||
|
||||
// Provider id (must be configured explicitly per firewall/authenticator if more than one provider is set)
|
||||
$defaultProvider = null;
|
||||
if (isset($firewall['provider'])) {
|
||||
if (!isset($providerIds[$normalizedName = str_replace('-', '_', $firewall['provider'])])) {
|
||||
throw new InvalidConfigurationException(sprintf('Invalid firewall "%s": user provider "%s" not found.', $id, $firewall['provider']));
|
||||
}
|
||||
$defaultProvider = $providerIds[$normalizedName];
|
||||
} else {
|
||||
if (count($providerIds) > 1) {
|
||||
throw new InvalidConfigurationException(sprintf('Not configuring explicitly the provider on "%s" firewall is ambiguous as there is more than one registered provider.', $id));
|
||||
}
|
||||
|
||||
} elseif (1 === count($providerIds)) {
|
||||
$defaultProvider = reset($providerIds);
|
||||
} elseif ($providerIds) {
|
||||
throw new InvalidConfigurationException(sprintf('Not configuring explicitly the provider on "%s" firewall is ambiguous as there is more than one registered provider.', $id));
|
||||
}
|
||||
|
||||
$config->replaceArgument(5, $defaultProvider);
|
||||
@ -399,7 +397,7 @@ class SecurityExtension extends Extension
|
||||
return $this->contextListeners[$contextKey] = $listenerId;
|
||||
}
|
||||
|
||||
private function createAuthenticationListeners($container, $id, $firewall, &$authenticationProviders, $defaultProvider, array $providerIds, $defaultEntryPoint)
|
||||
private function createAuthenticationListeners($container, $id, $firewall, &$authenticationProviders, $defaultProvider = null, array $providerIds, $defaultEntryPoint)
|
||||
{
|
||||
$listeners = array();
|
||||
$hasListeners = false;
|
||||
@ -415,7 +413,7 @@ class SecurityExtension extends Extension
|
||||
}
|
||||
$userProvider = $providerIds[$normalizedName];
|
||||
} else {
|
||||
$userProvider = $defaultProvider;
|
||||
$userProvider = $defaultProvider ?: $this->getFirstProvider($id, $key, $providerIds);
|
||||
}
|
||||
|
||||
list($provider, $listenerId, $defaultEntryPoint) = $factory->create($container, $id, $firewall[$key], $userProvider, $defaultEntryPoint);
|
||||
@ -598,7 +596,7 @@ class SecurityExtension extends Extension
|
||||
|
||||
private function createSwitchUserListener($container, $id, $config, $defaultProvider, $stateless)
|
||||
{
|
||||
$userProvider = isset($config['provider']) ? $this->getUserProviderId($config['provider']) : $defaultProvider;
|
||||
$userProvider = isset($config['provider']) ? $this->getUserProviderId($config['provider']) : ($defaultProvider ?: $this->getFirstProvider($id, 'switch_user', $providerIds));
|
||||
|
||||
$switchUserListenerId = 'security.authentication.switchuser_listener.'.$id;
|
||||
$listener = $container->setDefinition($switchUserListenerId, new ChildDefinition('security.authentication.switchuser_listener'));
|
||||
@ -697,4 +695,14 @@ class SecurityExtension extends Extension
|
||||
|
||||
return $this->expressionLanguage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since version 3.4, to be removed in 4.0
|
||||
*/
|
||||
private function getFirstProvider($firewallName, $listenerName, array $providerIds)
|
||||
{
|
||||
@trigger_error(sprintf('Listener "%s" on firewall "%s" has no "provider" set but multiple providers exist. Using the first configured provider (%s) is deprecated since 3.4 and will throw an exception in 4.0, set the "provider" key on the firewall instead.', $listenerName, $firewallName, $first = array_keys($providerIds)[0]), E_USER_DEPRECATED);
|
||||
|
||||
return $providerIds[$first];
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
<services>
|
||||
<defaults public="false" />
|
||||
|
||||
<service id="Symfony\Bundle\SecurityBundle\Command\UserPasswordEncoderCommand">
|
||||
<service id="security.command.user_password_encoder" class="Symfony\Bundle\SecurityBundle\Command\UserPasswordEncoderCommand">
|
||||
<argument type="service" id="security.encoder_factory"/>
|
||||
<argument type="collection" /> <!-- encoders' user classes -->
|
||||
<tag name="console.command" command="security:encode-password" />
|
||||
|
@ -12,7 +12,6 @@
|
||||
namespace Symfony\Bundle\SecurityBundle\Tests\DependencyInjection;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Bundle\SecurityBundle\Command\UserPasswordEncoderCommand;
|
||||
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Bundle\SecurityBundle\SecurityBundle;
|
||||
@ -355,7 +354,7 @@ abstract class CompleteConfigurationTest extends TestCase
|
||||
|
||||
public function testUserPasswordEncoderCommandIsRegistered()
|
||||
{
|
||||
$this->assertTrue($this->getContainer('remember_me_options')->has(UserPasswordEncoderCommand::class));
|
||||
$this->assertTrue($this->getContainer('remember_me_options')->has('security.command.user_password_encoder'));
|
||||
}
|
||||
|
||||
public function testDefaultAccessDecisionManagerStrategyIsAffirmative()
|
||||
|
@ -147,6 +147,27 @@ class SecurityExtensionTest extends TestCase
|
||||
$this->assertTrue($container->getDefinition('security.authentication.switchuser_listener.some_firewall')->getArgument(9));
|
||||
}
|
||||
|
||||
public function testPerListenerProvider()
|
||||
{
|
||||
$container = $this->getRawContainer();
|
||||
$container->loadFromExtension('security', array(
|
||||
'providers' => array(
|
||||
'first' => array('id' => 'foo'),
|
||||
'second' => array('id' => 'bar'),
|
||||
),
|
||||
|
||||
'firewalls' => array(
|
||||
'default' => array(
|
||||
'http_basic' => array('provider' => 'second'),
|
||||
'logout_on_user_change' => true,
|
||||
),
|
||||
),
|
||||
));
|
||||
|
||||
$container->compile();
|
||||
$this->addToAssertionCount(1);
|
||||
}
|
||||
|
||||
protected function getRawContainer()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
|
@ -7,13 +7,13 @@
|
||||
<services>
|
||||
<defaults public="false" />
|
||||
|
||||
<service id="Symfony\Bridge\Twig\Command\DebugCommand">
|
||||
<service id="twig.command.debug" class="Symfony\Bridge\Twig\Command\DebugCommand">
|
||||
<argument type="service" id="twig" />
|
||||
<argument>%kernel.project_dir%</argument>
|
||||
<tag name="console.command" command="debug:twig" />
|
||||
</service>
|
||||
|
||||
<service id="Symfony\Bundle\TwigBundle\Command\LintCommand">
|
||||
<service id="twig.command.lint" class="Symfony\Bundle\TwigBundle\Command\LintCommand">
|
||||
<argument type="service" id="twig" />
|
||||
<tag name="console.command" command="lint:twig" />
|
||||
</service>
|
||||
|
@ -130,7 +130,7 @@ trait MemcachedTrait
|
||||
}
|
||||
|
||||
// set client's options
|
||||
unset($options['persistent_id'], $options['username'], $options['password'], $options['weight']);
|
||||
unset($options['persistent_id'], $options['username'], $options['password'], $options['weight'], $options['lazy']);
|
||||
$options = array_change_key_case($options, CASE_UPPER);
|
||||
$client->setOption(\Memcached::OPT_BINARY_PROTOCOL, true);
|
||||
$client->setOption(\Memcached::OPT_NO_BLOCK, true);
|
||||
|
@ -59,7 +59,7 @@ class CheckCircularReferencesPass implements CompilerPassInterface
|
||||
|
||||
if (empty($this->checkedNodes[$id])) {
|
||||
// Don't check circular references for lazy edges
|
||||
if (!$node->getValue() || !$edge->isLazy()) {
|
||||
if (!$node->getValue() || (!$edge->isLazy() && !$edge->isWeak())) {
|
||||
$searchKey = array_search($id, $this->currentPath);
|
||||
$this->currentPath[] = $id;
|
||||
|
||||
|
@ -52,12 +52,12 @@ class ResolveHotPathPass extends AbstractRecursivePass
|
||||
if ($value instanceof ArgumentInterface) {
|
||||
return $value;
|
||||
}
|
||||
if ($value instanceof Definition && $isRoot && (isset($this->resolvedIds[$this->currentId]) || !$value->hasTag($this->tagName))) {
|
||||
return $value;
|
||||
if ($value instanceof Definition && $isRoot && (isset($this->resolvedIds[$this->currentId]) || !$value->hasTag($this->tagName) || $value->isDeprecated())) {
|
||||
return $value->isDeprecated() ? $value->clearTag($this->tagName) : $value;
|
||||
}
|
||||
if ($value instanceof Reference && ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE !== $value->getInvalidBehavior() && $this->container->has($id = (string) $value)) {
|
||||
$definition = $this->container->findDefinition($id);
|
||||
if (!$definition->hasTag($this->tagName)) {
|
||||
if (!$definition->hasTag($this->tagName) && !$definition->isDeprecated()) {
|
||||
$this->resolvedIds[$id] = true;
|
||||
$definition->addTag($this->tagName);
|
||||
parent::processValue($definition, false);
|
||||
|
@ -16,6 +16,7 @@ use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
|
||||
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
|
||||
use Symfony\Component\DependencyInjection\Variable;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Compiler\AnalyzeServiceReferencesPass;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Container;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
@ -67,6 +68,7 @@ class PhpDumper extends Dumper
|
||||
private $hotPathTag;
|
||||
private $inlineRequires;
|
||||
private $inlinedRequires = array();
|
||||
private $circularReferences = array();
|
||||
|
||||
/**
|
||||
* @var ProxyDumper
|
||||
@ -134,6 +136,14 @@ class PhpDumper extends Dumper
|
||||
|
||||
$this->initializeMethodNamesMap('Container' === $baseClass ? Container::class : $baseClass);
|
||||
|
||||
(new AnalyzeServiceReferencesPass())->process($this->container);
|
||||
$this->circularReferences = array();
|
||||
$checkedNodes = array();
|
||||
foreach ($this->container->getCompiler()->getServiceReferenceGraph()->getNodes() as $id => $node) {
|
||||
$currentPath = array($id => $id);
|
||||
$this->analyzeCircularReferences($node->getOutEdges(), $checkedNodes, $currentPath);
|
||||
}
|
||||
|
||||
$this->docStar = $options['debug'] ? '*' : '';
|
||||
|
||||
if (!empty($options['file']) && is_dir($dir = dirname($options['file']))) {
|
||||
@ -235,6 +245,7 @@ EOF;
|
||||
|
||||
$this->targetDirRegex = null;
|
||||
$this->inlinedRequires = array();
|
||||
$this->circularReferences = array();
|
||||
|
||||
$unusedEnvs = array();
|
||||
foreach ($this->container->getEnvCounters() as $env => $use) {
|
||||
@ -267,19 +278,19 @@ EOF;
|
||||
|
||||
array_unshift($inlinedDefinitions, $definition);
|
||||
|
||||
$collectLineage = $this->inlineRequires && !($this->hotPathTag && $definition->hasTag($this->hotPathTag));
|
||||
$isNonLazyShared = !$this->getProxyDumper()->isProxyCandidate($definition) && $definition->isShared();
|
||||
$collectLineage = $this->inlineRequires && !$this->isHotPath($definition);
|
||||
$isNonLazyShared = isset($this->circularReferences[$cId]) && !$this->getProxyDumper()->isProxyCandidate($definition) && $definition->isShared();
|
||||
$lineage = $calls = $behavior = array();
|
||||
foreach ($inlinedDefinitions as $iDefinition) {
|
||||
if ($collectLineage && $class = is_array($factory = $iDefinition->getFactory()) && is_string($factory[0]) ? $factory[0] : $iDefinition->getClass()) {
|
||||
if ($collectLineage && !$iDefinition->isDeprecated() && $class = is_array($factory = $iDefinition->getFactory()) && is_string($factory[0]) ? $factory[0] : $iDefinition->getClass()) {
|
||||
$this->collectLineage($class, $lineage);
|
||||
}
|
||||
$this->getServiceCallsFromArguments($iDefinition->getArguments(), $calls, $behavior, $isNonLazyShared);
|
||||
$this->getServiceCallsFromArguments($iDefinition->getArguments(), $calls, $behavior, $isNonLazyShared, $cId);
|
||||
$isPreInstantiation = $isNonLazyShared && $iDefinition !== $definition && !$this->hasReference($cId, $iDefinition->getMethodCalls(), true) && !$this->hasReference($cId, $iDefinition->getProperties(), true);
|
||||
$this->getServiceCallsFromArguments($iDefinition->getMethodCalls(), $calls, $behavior, $isPreInstantiation);
|
||||
$this->getServiceCallsFromArguments($iDefinition->getProperties(), $calls, $behavior, $isPreInstantiation);
|
||||
$this->getServiceCallsFromArguments(array($iDefinition->getConfigurator()), $calls, $behavior, $isPreInstantiation);
|
||||
$this->getServiceCallsFromArguments(array($iDefinition->getFactory()), $calls, $behavior, $isNonLazyShared);
|
||||
$this->getServiceCallsFromArguments($iDefinition->getMethodCalls(), $calls, $behavior, $isPreInstantiation, $cId);
|
||||
$this->getServiceCallsFromArguments($iDefinition->getProperties(), $calls, $behavior, $isPreInstantiation, $cId);
|
||||
$this->getServiceCallsFromArguments(array($iDefinition->getConfigurator()), $calls, $behavior, $isPreInstantiation, $cId);
|
||||
$this->getServiceCallsFromArguments(array($iDefinition->getFactory()), $calls, $behavior, $isNonLazyShared, $cId);
|
||||
}
|
||||
|
||||
$code = '';
|
||||
@ -333,6 +344,33 @@ EOTXT
|
||||
return $code;
|
||||
}
|
||||
|
||||
private function analyzeCircularReferences(array $edges, &$checkedNodes, &$currentPath)
|
||||
{
|
||||
foreach ($edges as $edge) {
|
||||
$node = $edge->getDestNode();
|
||||
$id = $node->getId();
|
||||
|
||||
if (isset($checkedNodes[$id])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($node->getValue() && ($edge->isLazy() || $edge->isWeak())) {
|
||||
// no-op
|
||||
} elseif (isset($currentPath[$id])) {
|
||||
foreach (array_reverse($currentPath) as $parentId) {
|
||||
$this->circularReferences[$parentId][$id] = $id;
|
||||
$id = $parentId;
|
||||
}
|
||||
} else {
|
||||
$currentPath[$id] = $id;
|
||||
$this->analyzeCircularReferences($node->getOutEdges(), $checkedNodes, $currentPath);
|
||||
}
|
||||
|
||||
$checkedNodes[$id] = true;
|
||||
array_pop($currentPath);
|
||||
}
|
||||
}
|
||||
|
||||
private function collectLineage($class, array &$lineage)
|
||||
{
|
||||
if (isset($lineage[$class])) {
|
||||
@ -526,7 +564,7 @@ EOTXT
|
||||
}
|
||||
|
||||
foreach ($definition->getArguments() as $arg) {
|
||||
if (!$arg || ($arg instanceof Reference && 'service_container' === (string) $arg)) {
|
||||
if (!$arg) {
|
||||
continue;
|
||||
}
|
||||
if (is_array($arg) && 3 >= count($arg)) {
|
||||
@ -534,7 +572,7 @@ EOTXT
|
||||
if ($this->dumpValue($k) !== $this->dumpValue($k, false)) {
|
||||
return false;
|
||||
}
|
||||
if (!$v || ($v instanceof Reference && 'service_container' === (string) $v)) {
|
||||
if (!$v) {
|
||||
continue;
|
||||
}
|
||||
if ($v instanceof Reference && $this->container->has($id = (string) $v) && $this->container->findDefinition($id)->isSynthetic()) {
|
||||
@ -694,7 +732,7 @@ EOTXT
|
||||
$lazyInitialization = '';
|
||||
}
|
||||
|
||||
$asFile = $this->asFiles && $definition->isShared() && !($this->hotPathTag && $definition->hasTag($this->hotPathTag));
|
||||
$asFile = $this->asFiles && $definition->isShared() && !$this->isHotPath($definition);
|
||||
$methodName = $this->generateMethodName($id);
|
||||
if ($asFile) {
|
||||
$file = $methodName.'.php';
|
||||
@ -755,7 +793,7 @@ EOF;
|
||||
$definitions = $this->container->getDefinitions();
|
||||
ksort($definitions);
|
||||
foreach ($definitions as $id => $definition) {
|
||||
if ($definition->isSynthetic() || ($this->asFiles && $definition->isShared() && !($this->hotPathTag && $definition->hasTag($this->hotPathTag)))) {
|
||||
if ($definition->isSynthetic() || ($this->asFiles && $definition->isShared() && !$this->isHotPath($definition))) {
|
||||
continue;
|
||||
}
|
||||
if ($definition->isPublic()) {
|
||||
@ -773,7 +811,7 @@ EOF;
|
||||
$definitions = $this->container->getDefinitions();
|
||||
ksort($definitions);
|
||||
foreach ($definitions as $id => $definition) {
|
||||
if (!$definition->isSynthetic() && $definition->isShared() && !($this->hotPathTag && $definition->hasTag($this->hotPathTag))) {
|
||||
if (!$definition->isSynthetic() && $definition->isShared() && !$this->isHotPath($definition)) {
|
||||
$code = $this->addService($id, $definition, $file);
|
||||
yield $file => $code;
|
||||
}
|
||||
@ -996,7 +1034,7 @@ EOF;
|
||||
$definitions = $this->container->getDefinitions();
|
||||
ksort($definitions);
|
||||
foreach ($definitions as $id => $definition) {
|
||||
if (!$definition->isSynthetic() && $definition->isPublic() && (!$this->asFiles || !$definition->isShared() || ($this->hotPathTag && $definition->hasTag($this->hotPathTag)))) {
|
||||
if (!$definition->isSynthetic() && $definition->isPublic() && (!$this->asFiles || !$definition->isShared() || $this->isHotPath($definition))) {
|
||||
$code .= ' '.$this->export($id).' => '.$this->export($this->generateMethodName($id)).",\n";
|
||||
}
|
||||
}
|
||||
@ -1010,7 +1048,7 @@ EOF;
|
||||
$definitions = $this->container->getDefinitions();
|
||||
ksort($definitions);
|
||||
foreach ($definitions as $id => $definition) {
|
||||
if (!$definition->isSynthetic() && $definition->isPublic() && $definition->isShared() && !($this->hotPathTag && $definition->hasTag($this->hotPathTag))) {
|
||||
if (!$definition->isSynthetic() && $definition->isPublic() && $definition->isShared() && !$this->isHotPath($definition)) {
|
||||
$code .= sprintf(" %s => __DIR__.'/%s.php',\n", $this->export($id), $this->generateMethodName($id));
|
||||
}
|
||||
}
|
||||
@ -1260,16 +1298,16 @@ EOF;
|
||||
return implode(' && ', $conditions);
|
||||
}
|
||||
|
||||
private function getServiceCallsFromArguments(array $arguments, array &$calls, array &$behavior, bool $isPreInstantiation)
|
||||
private function getServiceCallsFromArguments(array $arguments, array &$calls, array &$behavior, bool $isPreInstantiation, string $callerId)
|
||||
{
|
||||
foreach ($arguments as $argument) {
|
||||
if (is_array($argument)) {
|
||||
$this->getServiceCallsFromArguments($argument, $calls, $behavior, $isPreInstantiation);
|
||||
$this->getServiceCallsFromArguments($argument, $calls, $behavior, $isPreInstantiation, $callerId);
|
||||
} elseif ($argument instanceof Reference) {
|
||||
$id = (string) $argument;
|
||||
|
||||
if (!isset($calls[$id])) {
|
||||
$calls[$id] = (int) ($isPreInstantiation && $this->container->has($id) && !$this->container->findDefinition($id)->isSynthetic());
|
||||
$calls[$id] = (int) ($isPreInstantiation && isset($this->circularReferences[$callerId][$id]));
|
||||
}
|
||||
if (!isset($behavior[$id])) {
|
||||
$behavior[$id] = $argument->getInvalidBehavior();
|
||||
@ -1321,6 +1359,10 @@ EOF;
|
||||
|
||||
private function hasReference(string $id, array $arguments, bool $deep = false, array &$visited = array()): bool
|
||||
{
|
||||
if (!isset($this->circularReferences[$id])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($arguments as $argument) {
|
||||
if (is_array($argument)) {
|
||||
if ($this->hasReference($id, $argument, $deep, $visited)) {
|
||||
@ -1334,7 +1376,7 @@ EOF;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!$deep || isset($visited[$argumentId]) || 'service_container' === $argumentId) {
|
||||
if (!$deep || isset($visited[$argumentId]) || !isset($this->circularReferences[$id][$argumentId])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1570,7 +1612,7 @@ EOF;
|
||||
if ($definition->isShared()) {
|
||||
$code = sprintf('$this->%s[\'%s\'] = %s', $definition->isPublic() ? 'services' : 'privates', $id, $code);
|
||||
}
|
||||
} elseif ($this->asFiles && $definition->isShared() && !($this->hotPathTag && $definition->hasTag($this->hotPathTag))) {
|
||||
} elseif ($this->asFiles && $definition->isShared() && !$this->isHotPath($definition)) {
|
||||
$code = sprintf("\$this->load(__DIR__.'/%s.php')", $this->generateMethodName($id));
|
||||
} else {
|
||||
$code = sprintf('$this->%s()', $this->generateMethodName($id));
|
||||
@ -1694,6 +1736,11 @@ EOF;
|
||||
return $this->expressionLanguage;
|
||||
}
|
||||
|
||||
private function isHotPath(Definition $definition)
|
||||
{
|
||||
return $this->hotPathTag && $definition->hasTag($this->hotPathTag) && !$definition->isDeprecated();
|
||||
}
|
||||
|
||||
private function export($value)
|
||||
{
|
||||
if (null !== $this->targetDirRegex && is_string($value) && preg_match($this->targetDirRegex, $value, $matches, PREG_OFFSET_CAPTURE)) {
|
||||
|
@ -34,11 +34,15 @@ class ResolveHotPathPassTest extends TestCase
|
||||
;
|
||||
|
||||
$container->register('lazy');
|
||||
$container->register('bar');
|
||||
$container->register('bar')->addArgument(new Reference('buz'));
|
||||
$container->register('baz')->addArgument(new Reference('lazy'));
|
||||
$container->register('baz')->addArgument(new Reference('lazy'));
|
||||
$container->register('bar')
|
||||
->addArgument(new Reference('buz'))
|
||||
->addArgument(new Reference('deprec_ref_notag'));
|
||||
$container->register('baz')
|
||||
->addArgument(new Reference('lazy'))
|
||||
->addArgument(new Reference('lazy'));
|
||||
$container->register('buz');
|
||||
$container->register('deprec_with_tag')->setDeprecated()->addTag('container.hot_path');
|
||||
$container->register('deprec_ref_notag')->setDeprecated();
|
||||
|
||||
(new ResolveHotPathPass())->process($container);
|
||||
|
||||
@ -47,5 +51,7 @@ class ResolveHotPathPassTest extends TestCase
|
||||
$this->assertTrue($container->getDefinition('buz')->hasTag('container.hot_path'));
|
||||
$this->assertFalse($container->getDefinition('baz')->hasTag('container.hot_path'));
|
||||
$this->assertFalse($container->getDefinition('service_container')->hasTag('container.hot_path'));
|
||||
$this->assertFalse($container->getDefinition('deprec_with_tag')->hasTag('container.hot_path'));
|
||||
$this->assertFalse($container->getDefinition('deprec_ref_notag')->hasTag('container.hot_path'));
|
||||
}
|
||||
}
|
||||
|
@ -176,7 +176,7 @@ class PhpDumperTest extends TestCase
|
||||
if ('\\' === DIRECTORY_SEPARATOR) {
|
||||
$dump = str_replace('\\\\Fixtures\\\\includes\\\\foo.php', '/Fixtures/includes/foo.php', $dump);
|
||||
}
|
||||
$this->assertStringMatchesFormatFile(self::$fixturesPath.'/php/services9_as_files.txt', $dump);
|
||||
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services9_as_files.txt', $dump);
|
||||
}
|
||||
|
||||
public function testServicesWithAnonymousFactories()
|
||||
|
@ -66,18 +66,12 @@ use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
|
||||
// This file has been auto-generated by the Symfony Dependency Injection Component for internal use.
|
||||
// Returns the public 'configured_service' shared service.
|
||||
|
||||
$a = ($this->services['baz'] ?? $this->load(__DIR__.'/getBazService.php'));
|
||||
|
||||
if (isset($this->services['configured_service'])) {
|
||||
return $this->services['configured_service'];
|
||||
}
|
||||
|
||||
$b = new \ConfClass();
|
||||
$b->setFoo($a);
|
||||
$a = new \ConfClass();
|
||||
$a->setFoo(($this->services['baz'] ?? $this->load(__DIR__.'/getBazService.php')));
|
||||
|
||||
$this->services['configured_service'] = $instance = new \stdClass();
|
||||
|
||||
$b->configureStdClass($instance);
|
||||
$a->configureStdClass($instance);
|
||||
|
||||
return $instance;
|
||||
|
||||
@ -130,13 +124,7 @@ use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
|
||||
// This file has been auto-generated by the Symfony Dependency Injection Component for internal use.
|
||||
// Returns the public 'factory_service' shared service.
|
||||
|
||||
$a = ($this->services['foo.baz'] ?? $this->load(__DIR__.'/getFoo_BazService.php'));
|
||||
|
||||
if (isset($this->services['factory_service'])) {
|
||||
return $this->services['factory_service'];
|
||||
}
|
||||
|
||||
return $this->services['factory_service'] = $a->getInstance();
|
||||
return $this->services['factory_service'] = ($this->services['foo.baz'] ?? $this->load(__DIR__.'/getFoo_BazService.php'))->getInstance();
|
||||
|
||||
[Container%s/getFactoryServiceSimpleService.php] => <?php
|
||||
|
||||
@ -145,13 +133,7 @@ use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
|
||||
// This file has been auto-generated by the Symfony Dependency Injection Component for internal use.
|
||||
// Returns the public 'factory_service_simple' shared service.
|
||||
|
||||
$a = ($this->privates['factory_simple'] ?? $this->load(__DIR__.'/getFactorySimpleService.php'));
|
||||
|
||||
if (isset($this->services['factory_service_simple'])) {
|
||||
return $this->services['factory_service_simple'];
|
||||
}
|
||||
|
||||
return $this->services['factory_service_simple'] = $a->getInstance();
|
||||
return $this->services['factory_service_simple'] = ($this->privates['factory_simple'] ?? $this->load(__DIR__.'/getFactorySimpleService.php'))->getInstance();
|
||||
|
||||
[Container%s/getFactorySimpleService.php] => <?php
|
||||
|
||||
@ -173,10 +155,6 @@ use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
|
||||
|
||||
$a = ($this->services['foo.baz'] ?? $this->load(__DIR__.'/getFoo_BazService.php'));
|
||||
|
||||
if (isset($this->services['foo'])) {
|
||||
return $this->services['foo'];
|
||||
}
|
||||
|
||||
$this->services['foo'] = $instance = \Bar\FooClass::getInstance('foo', $a, array('bar' => 'foo is bar', 'foobar' => 'bar'), true, $this);
|
||||
|
||||
$instance->foo = 'bar';
|
||||
@ -413,10 +391,6 @@ class ProjectServiceContainer extends Container
|
||||
{
|
||||
$a = ($this->services['foo.baz'] ?? $this->load(__DIR__.'/getFoo_BazService.php'));
|
||||
|
||||
if (isset($this->services['bar'])) {
|
||||
return $this->services['bar'];
|
||||
}
|
||||
|
||||
$this->services['bar'] = $instance = new \Bar\FooClass('foo', $a, $this->getParameter('foo_bar'));
|
||||
|
||||
$a->configure($instance);
|
||||
|
@ -124,10 +124,6 @@ class ProjectServiceContainer extends Container
|
||||
{
|
||||
$a = ($this->services['foo.baz'] ?? $this->getFoo_BazService());
|
||||
|
||||
if (isset($this->services['bar'])) {
|
||||
return $this->services['bar'];
|
||||
}
|
||||
|
||||
$this->services['bar'] = $instance = new \Bar\FooClass('foo', $a, $this->getParameter('foo_bar'));
|
||||
|
||||
$a->configure($instance);
|
||||
@ -166,18 +162,12 @@ class ProjectServiceContainer extends Container
|
||||
*/
|
||||
protected function getConfiguredServiceService()
|
||||
{
|
||||
$a = ($this->services['baz'] ?? $this->getBazService());
|
||||
|
||||
if (isset($this->services['configured_service'])) {
|
||||
return $this->services['configured_service'];
|
||||
}
|
||||
|
||||
$b = new \ConfClass();
|
||||
$b->setFoo($a);
|
||||
$a = new \ConfClass();
|
||||
$a->setFoo(($this->services['baz'] ?? $this->getBazService()));
|
||||
|
||||
$this->services['configured_service'] = $instance = new \stdClass();
|
||||
|
||||
$b->configureStdClass($instance);
|
||||
$a->configureStdClass($instance);
|
||||
|
||||
return $instance;
|
||||
}
|
||||
@ -237,13 +227,7 @@ class ProjectServiceContainer extends Container
|
||||
*/
|
||||
protected function getFactoryServiceService()
|
||||
{
|
||||
$a = ($this->services['foo.baz'] ?? $this->getFoo_BazService());
|
||||
|
||||
if (isset($this->services['factory_service'])) {
|
||||
return $this->services['factory_service'];
|
||||
}
|
||||
|
||||
return $this->services['factory_service'] = $a->getInstance();
|
||||
return $this->services['factory_service'] = ($this->services['foo.baz'] ?? $this->getFoo_BazService())->getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -253,13 +237,7 @@ class ProjectServiceContainer extends Container
|
||||
*/
|
||||
protected function getFactoryServiceSimpleService()
|
||||
{
|
||||
$a = ($this->privates['factory_simple'] ?? $this->getFactorySimpleService());
|
||||
|
||||
if (isset($this->services['factory_service_simple'])) {
|
||||
return $this->services['factory_service_simple'];
|
||||
}
|
||||
|
||||
return $this->services['factory_service_simple'] = $a->getInstance();
|
||||
return $this->services['factory_service_simple'] = ($this->privates['factory_simple'] ?? $this->getFactorySimpleService())->getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -271,10 +249,6 @@ class ProjectServiceContainer extends Container
|
||||
{
|
||||
$a = ($this->services['foo.baz'] ?? $this->getFoo_BazService());
|
||||
|
||||
if (isset($this->services['foo'])) {
|
||||
return $this->services['foo'];
|
||||
}
|
||||
|
||||
$this->services['foo'] = $instance = \Bar\FooClass::getInstance('foo', $a, array('bar' => 'foo is bar', 'foobar' => 'bar'), true, $this);
|
||||
|
||||
$instance->foo = 'bar';
|
||||
|
@ -72,13 +72,7 @@ class ProjectServiceContainer extends Container
|
||||
*/
|
||||
protected function getBarServiceService()
|
||||
{
|
||||
$a = ($this->privates['baz_service'] ?? $this->privates['baz_service'] = new \stdClass());
|
||||
|
||||
if (isset($this->services['bar_service'])) {
|
||||
return $this->services['bar_service'];
|
||||
}
|
||||
|
||||
return $this->services['bar_service'] = new \stdClass($a);
|
||||
return $this->services['bar_service'] = new \stdClass(($this->privates['baz_service'] ?? $this->privates['baz_service'] = new \stdClass()));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -164,10 +158,6 @@ class ProjectServiceContainer extends Container
|
||||
{
|
||||
$a = ($this->services['translator.loader_3'] ?? $this->services['translator.loader_3'] = new \stdClass());
|
||||
|
||||
if (isset($this->services['translator_3'])) {
|
||||
return $this->services['translator_3'];
|
||||
}
|
||||
|
||||
$this->services['translator_3'] = $instance = new \Symfony\Component\DependencyInjection\Tests\Fixtures\StubbedTranslator(new \Symfony\Component\DependencyInjection\ServiceLocator(array('translator.loader_3' => function () {
|
||||
return ($this->services['translator.loader_3'] ?? $this->services['translator.loader_3'] = new \stdClass());
|
||||
})));
|
||||
|
@ -63,13 +63,7 @@ class ProjectServiceContainer extends Container
|
||||
*/
|
||||
protected function getBarServiceService()
|
||||
{
|
||||
$a = ($this->privates['baz_service'] ?? $this->privates['baz_service'] = new \stdClass());
|
||||
|
||||
if (isset($this->services['bar_service'])) {
|
||||
return $this->services['bar_service'];
|
||||
}
|
||||
|
||||
return $this->services['bar_service'] = new \stdClass($a);
|
||||
return $this->services['bar_service'] = new \stdClass(($this->privates['baz_service'] ?? $this->privates['baz_service'] = new \stdClass()));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -79,12 +73,6 @@ class ProjectServiceContainer extends Container
|
||||
*/
|
||||
protected function getFooServiceService()
|
||||
{
|
||||
$a = ($this->privates['baz_service'] ?? $this->privates['baz_service'] = new \stdClass());
|
||||
|
||||
if (isset($this->services['foo_service'])) {
|
||||
return $this->services['foo_service'];
|
||||
}
|
||||
|
||||
return $this->services['foo_service'] = new \stdClass($a);
|
||||
return $this->services['foo_service'] = new \stdClass(($this->privates['baz_service'] ?? $this->privates['baz_service'] = new \stdClass()));
|
||||
}
|
||||
}
|
||||
|
@ -56,11 +56,13 @@ class PropertyNormalizer extends AbstractObjectNormalizer
|
||||
$class = new \ReflectionClass($class);
|
||||
|
||||
// We look for at least one non-static property
|
||||
foreach ($class->getProperties() as $property) {
|
||||
if (!$property->isStatic()) {
|
||||
return true;
|
||||
do {
|
||||
foreach ($class->getProperties() as $property) {
|
||||
if (!$property->isStatic()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while ($class = $class->getParentClass());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -441,6 +441,11 @@ class PropertyNormalizerTest extends TestCase
|
||||
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
public function testInheritedPropertiesSupport()
|
||||
{
|
||||
$this->assertTrue($this->normalizer->supportsNormalization(new PropertyChildDummy()));
|
||||
}
|
||||
}
|
||||
|
||||
class PropertyDummy
|
||||
@ -509,3 +514,12 @@ class StaticPropertyDummy
|
||||
{
|
||||
private static $property = 'value';
|
||||
}
|
||||
|
||||
class PropertyParentDummy
|
||||
{
|
||||
private $foo = 'bar';
|
||||
}
|
||||
|
||||
class PropertyChildDummy extends PropertyParentDummy
|
||||
{
|
||||
}
|
||||
|
Reference in New Issue
Block a user