Merge branch '3.4' into 4.1
* 3.4: fix cs SCA: consolidate non empty array checks across codebase [cs] correct invalid @param types [Bridge/PhpUnit] Use composer to download phpunit [DI] fix taking lazy services into account when dumping the container [Form] Fixed empty data for compound date interval [Cache] fix optimizing Psr6Cache for AdapterInterface pools deal with explicitly enabled workflow nodes
This commit is contained in:
commit
713b7986fe
@ -11,7 +11,7 @@
|
||||
*/
|
||||
|
||||
// Please update when phpunit needs to be reinstalled with fresh deps:
|
||||
// Cache-Id-Version: 2017-11-22 09:30 UTC
|
||||
// Cache-Id-Version: 2018-11-20 15:30 UTC
|
||||
|
||||
error_reporting(-1);
|
||||
|
||||
@ -89,29 +89,7 @@ if (!file_exists("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit") || md5_file(__
|
||||
|
||||
@mkdir($PHPUNIT_DIR, 0777, true);
|
||||
chdir($PHPUNIT_DIR);
|
||||
if (file_exists("phpunit-$PHPUNIT_VERSION")) {
|
||||
passthru(sprintf('\\' === DIRECTORY_SEPARATOR ? '(del /S /F /Q %s & rmdir %1$s) >nul': 'rm -rf %s', "phpunit-$PHPUNIT_VERSION"));
|
||||
}
|
||||
if (extension_loaded('openssl') && filter_var(ini_get('allow_url_fopen'), FILTER_VALIDATE_BOOLEAN) && !isset($_SERVER['http_proxy']) && !isset($_SERVER['https_proxy'])) {
|
||||
$remoteZip = "https://github.com/sebastianbergmann/phpunit/archive/$PHPUNIT_VERSION.zip";
|
||||
$remoteZipStream = @fopen($remoteZip, 'rb');
|
||||
if (!$remoteZipStream) {
|
||||
throw new \RuntimeException("Could not find $remoteZip");
|
||||
}
|
||||
stream_copy_to_stream($remoteZipStream, fopen("$PHPUNIT_VERSION.zip", 'wb'));
|
||||
} elseif ('\\' === DIRECTORY_SEPARATOR) {
|
||||
passthru("certutil -urlcache -split -f \"https://github.com/sebastianbergmann/phpunit/archive/$PHPUNIT_VERSION.zip\" $PHPUNIT_VERSION.zip");
|
||||
} else {
|
||||
@unlink("$PHPUNIT_VERSION.zip");
|
||||
passthru("wget -q https://github.com/sebastianbergmann/phpunit/archive/$PHPUNIT_VERSION.zip");
|
||||
}
|
||||
if (!class_exists('ZipArchive')) {
|
||||
throw new \Exception('simple-phpunit requires the "zip" PHP extension to be installed and enabled in order to uncompress the downloaded PHPUnit packages.');
|
||||
}
|
||||
$zip = new ZipArchive();
|
||||
$zip->open("$PHPUNIT_VERSION.zip");
|
||||
$zip->extractTo(getcwd());
|
||||
$zip->close();
|
||||
passthru("$COMPOSER create-project --no-install --prefer-dist --no-scripts --no-plugins --no-progress --ansi phpunit/phpunit phpunit-$PHPUNIT_VERSION \"$PHPUNIT_VERSION.*\"");
|
||||
chdir("phpunit-$PHPUNIT_VERSION");
|
||||
if ($SYMFONY_PHPUNIT_REMOVE) {
|
||||
passthru("$COMPOSER remove --no-update ".$SYMFONY_PHPUNIT_REMOVE);
|
||||
|
@ -18,6 +18,7 @@ use Symfony\Component\Asset\Package;
|
||||
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
|
||||
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
|
||||
use Symfony\Component\Config\Definition\ConfigurationInterface;
|
||||
use Symfony\Component\DependencyInjection\Exception\LogicException;
|
||||
use Symfony\Component\Form\Form;
|
||||
use Symfony\Component\Lock\Lock;
|
||||
use Symfony\Component\Lock\Store\SemaphoreStore;
|
||||
@ -220,10 +221,22 @@ class Configuration implements ConfigurationInterface
|
||||
$workflows = $v;
|
||||
unset($workflows['enabled']);
|
||||
|
||||
if (1 === \count($workflows) && isset($workflows[0]['enabled'])) {
|
||||
if (1 === \count($workflows) && isset($workflows[0]['enabled']) && 1 === \count($workflows[0])) {
|
||||
$workflows = array();
|
||||
}
|
||||
|
||||
if (1 === \count($workflows) && isset($workflows['workflows']) && array_keys($workflows['workflows']) !== range(0, \count($workflows) - 1) && !empty(array_diff(array_keys($workflows['workflows']), array('audit_trail', 'type', 'marking_store', 'supports', 'support_strategy', 'initial_place', 'places', 'transitions')))) {
|
||||
$workflows = $workflows['workflows'];
|
||||
}
|
||||
|
||||
foreach ($workflows as $key => $workflow) {
|
||||
if (isset($workflow['enabled']) && false === $workflow['enabled']) {
|
||||
throw new LogicException(sprintf('Cannot disable a single workflow. Remove the configuration for the workflow "%s" instead.', $workflow['name']));
|
||||
}
|
||||
|
||||
unset($workflows[$key]['enabled']);
|
||||
}
|
||||
|
||||
$v = array(
|
||||
'enabled' => true,
|
||||
'workflows' => $workflows,
|
||||
|
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
$container->loadFromExtension('framework', array(
|
||||
'workflows' => array(
|
||||
'enabled' => true,
|
||||
'foo' => array(
|
||||
'type' => 'workflow',
|
||||
'supports' => array('Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest'),
|
||||
'initial_place' => 'bar',
|
||||
'places' => array('bar', 'baz'),
|
||||
'transitions' => array(
|
||||
'bar_baz' => array(
|
||||
'from' => array('foo'),
|
||||
'to' => array('bar'),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
$container->loadFromExtension('framework', array(
|
||||
'workflows' => array(
|
||||
'enabled' => true,
|
||||
'workflows' => array(
|
||||
'type' => 'workflow',
|
||||
'supports' => array('Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest'),
|
||||
'initial_place' => 'bar',
|
||||
'places' => array('bar', 'baz'),
|
||||
'transitions' => array(
|
||||
'bar_baz' => array(
|
||||
'from' => array('foo'),
|
||||
'to' => array('bar'),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" ?>
|
||||
<container xmlns="http://symfony.com/schema/dic/services"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:framework="http://symfony.com/schema/dic/symfony"
|
||||
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
|
||||
http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
|
||||
|
||||
<framework:config>
|
||||
<framework:workflow enabled="true" name="foo" type="workflow" initial-place="bar">
|
||||
<framework:support>Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest</framework:support>
|
||||
<framework:place>bar</framework:place>
|
||||
<framework:place>baz</framework:place>
|
||||
<framework:transition name="bar_baz">
|
||||
<framework:from>bar</framework:from>
|
||||
<framework:to>baz</framework:to>
|
||||
</framework:transition>
|
||||
</framework:workflow>
|
||||
</framework:config>
|
||||
</container>
|
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" ?>
|
||||
<container xmlns="http://symfony.com/schema/dic/services"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:framework="http://symfony.com/schema/dic/symfony"
|
||||
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
|
||||
http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
|
||||
|
||||
<framework:config>
|
||||
<framework:workflow enabled="true" name="workflows" type="workflow" initial-place="bar">
|
||||
<framework:support>Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest</framework:support>
|
||||
<framework:place>bar</framework:place>
|
||||
<framework:place>baz</framework:place>
|
||||
<framework:transition name="bar_baz">
|
||||
<framework:from>bar</framework:from>
|
||||
<framework:to>baz</framework:to>
|
||||
</framework:transition>
|
||||
</framework:workflow>
|
||||
</framework:config>
|
||||
</container>
|
@ -0,0 +1,16 @@
|
||||
framework:
|
||||
workflows:
|
||||
enabled: true
|
||||
workflows:
|
||||
foo:
|
||||
type: workflow
|
||||
supports:
|
||||
- Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest
|
||||
initial_place: bar
|
||||
places:
|
||||
- bar
|
||||
- baz
|
||||
transitions:
|
||||
bar_baz:
|
||||
from: [foo]
|
||||
to: [bar]
|
@ -0,0 +1,15 @@
|
||||
framework:
|
||||
workflows:
|
||||
enabled: true
|
||||
workflows:
|
||||
type: workflow
|
||||
supports:
|
||||
- Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest
|
||||
initial_place: bar
|
||||
places:
|
||||
- bar
|
||||
- baz
|
||||
transitions:
|
||||
bar_baz:
|
||||
from: [foo]
|
||||
to: [bar]
|
@ -409,6 +409,20 @@ abstract class FrameworkExtensionTest extends TestCase
|
||||
$this->assertTrue($container->hasDefinition('console.command.workflow_dump'));
|
||||
}
|
||||
|
||||
public function testExplicitlyEnabledWorkflows()
|
||||
{
|
||||
$container = $this->createContainerFromFile('workflows_explicitly_enabled');
|
||||
|
||||
$this->assertTrue($container->hasDefinition('workflow.foo.definition'));
|
||||
}
|
||||
|
||||
public function testExplicitlyEnabledWorkflowNamedWorkflows()
|
||||
{
|
||||
$container = $this->createContainerFromFile('workflows_explicitly_enabled_named_workflows');
|
||||
|
||||
$this->assertTrue($container->hasDefinition('workflow.workflows.definition'));
|
||||
}
|
||||
|
||||
public function testEnabledPhpErrorsConfig()
|
||||
{
|
||||
$container = $this->createContainerFromFile('php_errors_enabled');
|
||||
|
@ -15,7 +15,7 @@ use Psr\Cache\CacheException as Psr6CacheException;
|
||||
use Psr\Cache\CacheItemPoolInterface;
|
||||
use Psr\SimpleCache\CacheException as SimpleCacheException;
|
||||
use Psr\SimpleCache\CacheInterface;
|
||||
use Symfony\Component\Cache\Adapter\AbstractAdapter;
|
||||
use Symfony\Component\Cache\Adapter\AdapterInterface;
|
||||
use Symfony\Component\Cache\CacheItem;
|
||||
use Symfony\Component\Cache\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Cache\PruneableInterface;
|
||||
@ -30,27 +30,36 @@ class Psr6Cache implements CacheInterface, PruneableInterface, ResettableInterfa
|
||||
use ProxyTrait;
|
||||
|
||||
private $createCacheItem;
|
||||
private $cacheItemPrototype;
|
||||
|
||||
public function __construct(CacheItemPoolInterface $pool)
|
||||
{
|
||||
$this->pool = $pool;
|
||||
|
||||
if ($pool instanceof AbstractAdapter) {
|
||||
$this->createCacheItem = \Closure::bind(
|
||||
function ($key, $value, $allowInt = false) {
|
||||
if ($allowInt && \is_int($key)) {
|
||||
$key = (string) $key;
|
||||
} else {
|
||||
CacheItem::validateKey($key);
|
||||
}
|
||||
$f = $this->createCacheItem;
|
||||
|
||||
return $f($key, $value, false);
|
||||
},
|
||||
$pool,
|
||||
AbstractAdapter::class
|
||||
);
|
||||
if (!$pool instanceof AdapterInterface) {
|
||||
return;
|
||||
}
|
||||
$cacheItemPrototype = &$this->cacheItemPrototype;
|
||||
$createCacheItem = \Closure::bind(
|
||||
function ($key, $value, $allowInt = false) use (&$cacheItemPrototype) {
|
||||
$item = clone $cacheItemPrototype;
|
||||
$item->key = $allowInt && \is_int($key) ? (string) $key : CacheItem::validateKey($key);
|
||||
$item->value = $value;
|
||||
$item->isHit = false;
|
||||
|
||||
return $item;
|
||||
},
|
||||
null,
|
||||
CacheItem::class
|
||||
);
|
||||
$this->createCacheItem = function ($key, $value, $allowInt = false) use ($createCacheItem) {
|
||||
if (null === $this->cacheItemPrototype) {
|
||||
$this->get($allowInt && \is_int($key) ? (string) $key : $key);
|
||||
}
|
||||
$this->createCacheItem = $createCacheItem;
|
||||
|
||||
return $createCacheItem($key, $value, $allowInt);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -65,6 +74,10 @@ class Psr6Cache implements CacheInterface, PruneableInterface, ResettableInterfa
|
||||
} catch (Psr6CacheException $e) {
|
||||
throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
|
||||
}
|
||||
if (null === $this->cacheItemPrototype) {
|
||||
$this->cacheItemPrototype = clone $item;
|
||||
$this->cacheItemPrototype->set(null);
|
||||
}
|
||||
|
||||
return $item->isHit() ? $item->get() : $default;
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ trait AbstractTrait
|
||||
/**
|
||||
* Deletes all items in the pool.
|
||||
*
|
||||
* @param string The prefix used for all identifiers managed by this pool
|
||||
* @param string $namespace The prefix used for all identifiers managed by this pool
|
||||
*
|
||||
* @return bool True if the pool was successfully cleared, false otherwise
|
||||
*/
|
||||
|
@ -66,8 +66,8 @@ trait MemcachedTrait
|
||||
* - 'memcached://user:pass@localhost?weight=33'
|
||||
* - array(array('localhost', 11211, 33))
|
||||
*
|
||||
* @param array[]|string|string[] An array of servers, a DSN, or an array of DSNs
|
||||
* @param array An array of options
|
||||
* @param array[]|string|string[] $servers An array of servers, a DSN, or an array of DSNs
|
||||
* @param array $options An array of options
|
||||
*
|
||||
* @return \Memcached
|
||||
*
|
||||
|
@ -26,7 +26,7 @@ interface ConfigCacheFactoryInterface
|
||||
* @param string $file The absolute cache file path
|
||||
* @param callable $callable The callable to be executed when the cache needs to be filled (i. e. is not fresh). The cache will be passed as the only parameter to this callback
|
||||
*
|
||||
* @return ConfigCacheInterface $configCache The cache instance
|
||||
* @return ConfigCacheInterface The cache instance
|
||||
*/
|
||||
public function cache($file, $callable);
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ class ArrayNode extends BaseNode implements PrototypeNodeInterface
|
||||
/**
|
||||
* Gets the xml remappings that should be performed.
|
||||
*
|
||||
* @return array $remappings an array of the form array(array(string, string))
|
||||
* @return array an array of the form array(array(string, string))
|
||||
*/
|
||||
public function getXmlRemappings()
|
||||
{
|
||||
|
@ -368,7 +368,7 @@ abstract class BaseNode implements NodeInterface
|
||||
*
|
||||
* @param $value
|
||||
*
|
||||
* @return $value The normalized array value
|
||||
* @return The normalized array value
|
||||
*/
|
||||
protected function preNormalize($value)
|
||||
{
|
||||
|
@ -343,7 +343,7 @@ abstract class NodeDefinition implements NodeParentInterface
|
||||
/**
|
||||
* Instantiate and configure the node according to this definition.
|
||||
*
|
||||
* @return NodeInterface $node The node instance
|
||||
* @return NodeInterface The node instance
|
||||
*
|
||||
* @throws InvalidDefinitionException When the definition is invalid
|
||||
*/
|
||||
|
@ -276,7 +276,7 @@ class TableStyle
|
||||
/**
|
||||
* Gets crossing character.
|
||||
*
|
||||
* @return string $crossingChar
|
||||
* @return string
|
||||
*/
|
||||
public function getCrossingChar()
|
||||
{
|
||||
|
@ -21,8 +21,6 @@ interface InputAwareInterface
|
||||
{
|
||||
/**
|
||||
* Sets the Console Input.
|
||||
*
|
||||
* @param InputInterface
|
||||
*/
|
||||
public function setInput(InputInterface $input);
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ class AnalyzeServiceReferencesPass extends AbstractRecursivePass implements Repe
|
||||
private $hasProxyDumper;
|
||||
private $lazy;
|
||||
private $expressionLanguage;
|
||||
private $byConstructor;
|
||||
|
||||
/**
|
||||
* @param bool $onlyConstructorArguments Sets this Service Reference pass to ignore method calls
|
||||
@ -64,6 +65,7 @@ class AnalyzeServiceReferencesPass extends AbstractRecursivePass implements Repe
|
||||
$this->graph = $container->getCompiler()->getServiceReferenceGraph();
|
||||
$this->graph->clear();
|
||||
$this->lazy = false;
|
||||
$this->byConstructor = false;
|
||||
|
||||
foreach ($container->getAliases() as $id => $alias) {
|
||||
$targetId = $this->getDefinitionId((string) $alias);
|
||||
@ -100,7 +102,8 @@ class AnalyzeServiceReferencesPass extends AbstractRecursivePass implements Repe
|
||||
$targetDefinition,
|
||||
$value,
|
||||
$this->lazy || ($this->hasProxyDumper && $targetDefinition && $targetDefinition->isLazy()),
|
||||
ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $value->getInvalidBehavior()
|
||||
ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $value->getInvalidBehavior(),
|
||||
$this->byConstructor
|
||||
);
|
||||
|
||||
return $value;
|
||||
@ -118,8 +121,11 @@ class AnalyzeServiceReferencesPass extends AbstractRecursivePass implements Repe
|
||||
}
|
||||
$this->lazy = false;
|
||||
|
||||
$byConstructor = $this->byConstructor;
|
||||
$this->byConstructor = true;
|
||||
$this->processValue($value->getFactory());
|
||||
$this->processValue($value->getArguments());
|
||||
$this->byConstructor = $byConstructor;
|
||||
|
||||
if (!$this->onlyConstructorArguments) {
|
||||
$this->processValue($value->getProperties());
|
||||
|
@ -73,7 +73,7 @@ class ServiceReferenceGraph
|
||||
/**
|
||||
* Connects 2 nodes together in the Graph.
|
||||
*/
|
||||
public function connect(?string $sourceId, $sourceValue, ?string $destId, $destValue = null, $reference = null, bool $lazy = false, bool $weak = false)
|
||||
public function connect(?string $sourceId, $sourceValue, ?string $destId, $destValue = null, $reference = null, bool $lazy = false, bool $weak = false, bool $byConstructor = false)
|
||||
{
|
||||
if (null === $sourceId || null === $destId) {
|
||||
return;
|
||||
@ -81,7 +81,7 @@ class ServiceReferenceGraph
|
||||
|
||||
$sourceNode = $this->createNode($sourceId, $sourceValue);
|
||||
$destNode = $this->createNode($destId, $destValue);
|
||||
$edge = new ServiceReferenceGraphEdge($sourceNode, $destNode, $reference, $lazy, $weak);
|
||||
$edge = new ServiceReferenceGraphEdge($sourceNode, $destNode, $reference, $lazy, $weak, $byConstructor);
|
||||
|
||||
$sourceNode->addOutEdge($edge);
|
||||
$destNode->addInEdge($edge);
|
||||
|
@ -25,14 +25,16 @@ class ServiceReferenceGraphEdge
|
||||
private $value;
|
||||
private $lazy;
|
||||
private $weak;
|
||||
private $byConstructor;
|
||||
|
||||
public function __construct(ServiceReferenceGraphNode $sourceNode, ServiceReferenceGraphNode $destNode, $value = null, bool $lazy = false, bool $weak = false)
|
||||
public function __construct(ServiceReferenceGraphNode $sourceNode, ServiceReferenceGraphNode $destNode, $value = null, bool $lazy = false, bool $weak = false, bool $byConstructor = false)
|
||||
{
|
||||
$this->sourceNode = $sourceNode;
|
||||
$this->destNode = $destNode;
|
||||
$this->value = $value;
|
||||
$this->lazy = $lazy;
|
||||
$this->weak = $weak;
|
||||
$this->byConstructor = $byConstructor;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -84,4 +86,14 @@ class ServiceReferenceGraphEdge
|
||||
{
|
||||
return $this->weak;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the edge links with a constructor argument.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isReferencedByConstructor()
|
||||
{
|
||||
return $this->byConstructor;
|
||||
}
|
||||
}
|
||||
|
@ -406,7 +406,7 @@ class Definition
|
||||
/**
|
||||
* Sets the definition templates to conditionally apply on the current definition, keyed by parent interface/class.
|
||||
*
|
||||
* @param $instanceof ChildDefinition[]
|
||||
* @param ChildDefinition[] $instanceof
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
|
@ -155,12 +155,16 @@ class PhpDumper extends Dumper
|
||||
}
|
||||
}
|
||||
|
||||
(new AnalyzeServiceReferencesPass(false))->process($this->container);
|
||||
(new AnalyzeServiceReferencesPass(false, !$this->getProxyDumper() instanceof NullDumper))->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);
|
||||
foreach (array(true, false) as $byConstructor) {
|
||||
foreach ($this->container->getCompiler()->getServiceReferenceGraph()->getNodes() as $id => $node) {
|
||||
if (!$node->getValue() instanceof Definition) {
|
||||
continue;
|
||||
}
|
||||
$currentPath = array($id => true);
|
||||
$this->analyzeCircularReferences($node->getOutEdges(), $currentPath, $id, $byConstructor);
|
||||
}
|
||||
}
|
||||
$this->container->getCompiler()->getServiceReferenceGraph()->clear();
|
||||
|
||||
@ -303,27 +307,31 @@ EOF;
|
||||
return $this->proxyDumper;
|
||||
}
|
||||
|
||||
private function analyzeCircularReferences(array $edges, &$checkedNodes, &$currentPath)
|
||||
private function analyzeCircularReferences(array $edges, &$currentPath, $sourceId, $byConstructor)
|
||||
{
|
||||
foreach ($edges as $edge) {
|
||||
if ($byConstructor && !$edge->isReferencedByConstructor()) {
|
||||
continue;
|
||||
}
|
||||
$node = $edge->getDestNode();
|
||||
$id = $node->getId();
|
||||
|
||||
if ($node->getValue() && ($edge->isLazy() || $edge->isWeak())) {
|
||||
if (!$node->getValue() instanceof Definition || $sourceId === $id || $edge->isLazy() || $edge->isWeak()) {
|
||||
// no-op
|
||||
} elseif (isset($currentPath[$id])) {
|
||||
$currentId = $id;
|
||||
foreach (array_reverse($currentPath) as $parentId) {
|
||||
$this->circularReferences[$parentId][$currentId] = $currentId;
|
||||
if (!isset($this->circularReferences[$parentId][$currentId])) {
|
||||
$this->circularReferences[$parentId][$currentId] = $byConstructor;
|
||||
}
|
||||
if ($parentId === $id) {
|
||||
break;
|
||||
}
|
||||
$currentId = $parentId;
|
||||
}
|
||||
} elseif (!isset($checkedNodes[$id])) {
|
||||
$checkedNodes[$id] = true;
|
||||
} else {
|
||||
$currentPath[$id] = $id;
|
||||
$this->analyzeCircularReferences($node->getOutEdges(), $checkedNodes, $currentPath);
|
||||
$this->analyzeCircularReferences($node->getOutEdges(), $currentPath, $id, $byConstructor);
|
||||
unset($currentPath[$id]);
|
||||
}
|
||||
}
|
||||
@ -667,8 +675,14 @@ EOF;
|
||||
|
||||
private function addInlineReference(string $id, Definition $definition, string $targetId, bool $forConstructor): string
|
||||
{
|
||||
list($callCount, $behavior) = $this->serviceCalls[$targetId];
|
||||
|
||||
while ($this->container->hasAlias($targetId)) {
|
||||
$targetId = (string) $this->container->getAlias($targetId);
|
||||
}
|
||||
|
||||
if ($id === $targetId) {
|
||||
return $this->addInlineService($id, $definition, $definition, $forConstructor);
|
||||
return $this->addInlineService($id, $definition, $definition);
|
||||
}
|
||||
|
||||
if ('service_container' === $targetId || isset($this->referenceVariables[$targetId])) {
|
||||
@ -677,9 +691,7 @@ EOF;
|
||||
|
||||
$hasSelfRef = isset($this->circularReferences[$id][$targetId]);
|
||||
$forConstructor = $forConstructor && !isset($this->definitionVariables[$definition]);
|
||||
list($callCount, $behavior) = $this->serviceCalls[$targetId];
|
||||
|
||||
$code = $hasSelfRef && !$forConstructor ? $this->addInlineService($id, $definition, $definition, $forConstructor) : '';
|
||||
$code = $hasSelfRef && $this->circularReferences[$id][$targetId] && !$forConstructor ? $this->addInlineService($id, $definition, $definition) : '';
|
||||
|
||||
if (isset($this->referenceVariables[$targetId]) || (2 > $callCount && (!$hasSelfRef || !$forConstructor))) {
|
||||
return $code;
|
||||
@ -1222,7 +1234,7 @@ EOF;
|
||||
/*{$this->docStar}
|
||||
* Computes a dynamic parameter.
|
||||
*
|
||||
* @param string The name of the dynamic parameter to load
|
||||
* @param string \$name The name of the dynamic parameter to load
|
||||
*
|
||||
* @return mixed The value of the dynamic parameter
|
||||
*
|
||||
|
@ -115,7 +115,7 @@ class ProjectServiceContainer extends Container
|
||||
/**
|
||||
* Computes a dynamic parameter.
|
||||
*
|
||||
* @param string The name of the dynamic parameter to load
|
||||
* @param string $name The name of the dynamic parameter to load
|
||||
*
|
||||
* @return mixed The value of the dynamic parameter
|
||||
*
|
||||
|
@ -122,7 +122,7 @@ class ProjectServiceContainer extends Container
|
||||
/**
|
||||
* Computes a dynamic parameter.
|
||||
*
|
||||
* @param string The name of the dynamic parameter to load
|
||||
* @param string $name The name of the dynamic parameter to load
|
||||
*
|
||||
* @return mixed The value of the dynamic parameter
|
||||
*
|
||||
|
@ -132,7 +132,7 @@ class ProjectServiceContainer extends Container
|
||||
/**
|
||||
* Computes a dynamic parameter.
|
||||
*
|
||||
* @param string The name of the dynamic parameter to load
|
||||
* @param string $name The name of the dynamic parameter to load
|
||||
*
|
||||
* @return mixed The value of the dynamic parameter
|
||||
*
|
||||
|
@ -138,7 +138,7 @@ class Symfony_DI_PhpDumper_Test_EnvParameters extends Container
|
||||
/**
|
||||
* Computes a dynamic parameter.
|
||||
*
|
||||
* @param string The name of the dynamic parameter to load
|
||||
* @param string $name The name of the dynamic parameter to load
|
||||
*
|
||||
* @return mixed The value of the dynamic parameter
|
||||
*
|
||||
|
@ -102,7 +102,7 @@ class ProjectServiceContainer extends Container
|
||||
/**
|
||||
* Computes a dynamic parameter.
|
||||
*
|
||||
* @param string The name of the dynamic parameter to load
|
||||
* @param string $name The name of the dynamic parameter to load
|
||||
*
|
||||
* @return mixed The value of the dynamic parameter
|
||||
*
|
||||
|
@ -535,7 +535,7 @@ class ProjectServiceContainer extends Container
|
||||
/**
|
||||
* Computes a dynamic parameter.
|
||||
*
|
||||
* @param string The name of the dynamic parameter to load
|
||||
* @param string $name The name of the dynamic parameter to load
|
||||
*
|
||||
* @return mixed The value of the dynamic parameter
|
||||
*
|
||||
|
@ -475,7 +475,7 @@ class ProjectServiceContainer extends Container
|
||||
/**
|
||||
* Computes a dynamic parameter.
|
||||
*
|
||||
* @param string The name of the dynamic parameter to load
|
||||
* @param string $name The name of the dynamic parameter to load
|
||||
*
|
||||
* @return mixed The value of the dynamic parameter
|
||||
*
|
||||
|
@ -162,11 +162,16 @@ class Symfony_DI_PhpDumper_Test_Almost_Circular_Public extends Container
|
||||
*/
|
||||
protected function getConnectionService()
|
||||
{
|
||||
$a = new \stdClass();
|
||||
$a = ($this->services['dispatcher'] ?? $this->getDispatcherService());
|
||||
|
||||
$this->services['connection'] = $instance = new \stdClass(($this->services['dispatcher'] ?? $this->getDispatcherService()), $a);
|
||||
if (isset($this->services['connection'])) {
|
||||
return $this->services['connection'];
|
||||
}
|
||||
$b = new \stdClass();
|
||||
|
||||
$a->logger = ($this->services['logger'] ?? $this->getLoggerService());
|
||||
$this->services['connection'] = $instance = new \stdClass($a, $b);
|
||||
|
||||
$b->logger = ($this->services['logger'] ?? $this->getLoggerService());
|
||||
|
||||
return $instance;
|
||||
}
|
||||
@ -178,14 +183,19 @@ class Symfony_DI_PhpDumper_Test_Almost_Circular_Public extends Container
|
||||
*/
|
||||
protected function getConnection2Service()
|
||||
{
|
||||
$a = new \stdClass();
|
||||
$a = ($this->services['dispatcher2'] ?? $this->getDispatcher2Service());
|
||||
|
||||
$this->services['connection2'] = $instance = new \stdClass(($this->services['dispatcher2'] ?? $this->getDispatcher2Service()), $a);
|
||||
if (isset($this->services['connection2'])) {
|
||||
return $this->services['connection2'];
|
||||
}
|
||||
$b = new \stdClass();
|
||||
|
||||
$b = new \stdClass($instance);
|
||||
$b->handler2 = new \stdClass(($this->services['manager2'] ?? $this->getManager2Service()));
|
||||
$this->services['connection2'] = $instance = new \stdClass($a, $b);
|
||||
|
||||
$a->logger2 = $b;
|
||||
$c = new \stdClass($instance);
|
||||
$c->handler2 = new \stdClass(($this->services['manager2'] ?? $this->getManager2Service()));
|
||||
|
||||
$b->logger2 = $c;
|
||||
|
||||
return $instance;
|
||||
}
|
||||
@ -425,7 +435,13 @@ class Symfony_DI_PhpDumper_Test_Almost_Circular_Public extends Container
|
||||
*/
|
||||
protected function getSubscriberService()
|
||||
{
|
||||
return $this->services['subscriber'] = new \stdClass(($this->services['manager'] ?? $this->getManagerService()));
|
||||
$a = ($this->services['manager'] ?? $this->getManagerService());
|
||||
|
||||
if (isset($this->services['subscriber'])) {
|
||||
return $this->services['subscriber'];
|
||||
}
|
||||
|
||||
return $this->services['subscriber'] = new \stdClass($a);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -125,7 +125,7 @@ class ProjectServiceContainer extends Container
|
||||
/**
|
||||
* Computes a dynamic parameter.
|
||||
*
|
||||
* @param string The name of the dynamic parameter to load
|
||||
* @param string $name The name of the dynamic parameter to load
|
||||
*
|
||||
* @return mixed The value of the dynamic parameter
|
||||
*
|
||||
|
@ -104,7 +104,7 @@ class Symfony_DI_PhpDumper_Test_Base64Parameters extends Container
|
||||
/**
|
||||
* Computes a dynamic parameter.
|
||||
*
|
||||
* @param string The name of the dynamic parameter to load
|
||||
* @param string $name The name of the dynamic parameter to load
|
||||
*
|
||||
* @return mixed The value of the dynamic parameter
|
||||
*
|
||||
|
@ -104,7 +104,7 @@ class Symfony_DI_PhpDumper_Test_CsvParameters extends Container
|
||||
/**
|
||||
* Computes a dynamic parameter.
|
||||
*
|
||||
* @param string The name of the dynamic parameter to load
|
||||
* @param string $name The name of the dynamic parameter to load
|
||||
*
|
||||
* @return mixed The value of the dynamic parameter
|
||||
*
|
||||
|
@ -128,7 +128,7 @@ class ProjectServiceContainer extends Container
|
||||
/**
|
||||
* Computes a dynamic parameter.
|
||||
*
|
||||
* @param string The name of the dynamic parameter to load
|
||||
* @param string $name The name of the dynamic parameter to load
|
||||
*
|
||||
* @return mixed The value of the dynamic parameter
|
||||
*
|
||||
|
@ -475,7 +475,7 @@ class Symfony_DI_PhpDumper_Errored_Definition extends Container
|
||||
/**
|
||||
* Computes a dynamic parameter.
|
||||
*
|
||||
* @param string The name of the dynamic parameter to load
|
||||
* @param string $name The name of the dynamic parameter to load
|
||||
*
|
||||
* @return mixed The value of the dynamic parameter
|
||||
*
|
||||
|
@ -152,7 +152,7 @@ class ProjectServiceContainer extends Container
|
||||
/**
|
||||
* Computes a dynamic parameter.
|
||||
*
|
||||
* @param string The name of the dynamic parameter to load
|
||||
* @param string $name The name of the dynamic parameter to load
|
||||
*
|
||||
* @return mixed The value of the dynamic parameter
|
||||
*
|
||||
|
@ -105,7 +105,7 @@ class Symfony_DI_PhpDumper_Test_JsonParameters extends Container
|
||||
/**
|
||||
* Computes a dynamic parameter.
|
||||
*
|
||||
* @param string The name of the dynamic parameter to load
|
||||
* @param string $name The name of the dynamic parameter to load
|
||||
*
|
||||
* @return mixed The value of the dynamic parameter
|
||||
*
|
||||
|
@ -130,7 +130,7 @@ class Symfony_DI_PhpDumper_Test_Rot13Parameters extends Container
|
||||
/**
|
||||
* Computes a dynamic parameter.
|
||||
*
|
||||
* @param string The name of the dynamic parameter to load
|
||||
* @param string $name The name of the dynamic parameter to load
|
||||
*
|
||||
* @return mixed The value of the dynamic parameter
|
||||
*
|
||||
|
@ -38,7 +38,7 @@ class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate
|
||||
/**
|
||||
* Getter for subject property.
|
||||
*
|
||||
* @return mixed $subject The observer subject
|
||||
* @return mixed The observer subject
|
||||
*/
|
||||
public function getSubject()
|
||||
{
|
||||
|
@ -38,9 +38,9 @@ class DateIntervalType extends AbstractType
|
||||
'seconds',
|
||||
);
|
||||
private static $widgets = array(
|
||||
'text' => 'Symfony\Component\Form\Extension\Core\Type\TextType',
|
||||
'integer' => 'Symfony\Component\Form\Extension\Core\Type\IntegerType',
|
||||
'choice' => 'Symfony\Component\Form\Extension\Core\Type\ChoiceType',
|
||||
'text' => TextType::class,
|
||||
'integer' => IntegerType::class,
|
||||
'choice' => ChoiceType::class,
|
||||
);
|
||||
|
||||
/**
|
||||
@ -96,31 +96,23 @@ class DateIntervalType extends AbstractType
|
||||
if ('single_text' === $options['widget']) {
|
||||
$builder->addViewTransformer(new DateIntervalToStringTransformer($format));
|
||||
} else {
|
||||
$childOptions = array();
|
||||
foreach ($this->timeParts as $part) {
|
||||
if ($options['with_'.$part]) {
|
||||
$childOptions[$part] = array(
|
||||
$childOptions = array(
|
||||
'error_bubbling' => true,
|
||||
'label' => $options['labels'][$part],
|
||||
// Append generic carry-along options
|
||||
'required' => $options['required'],
|
||||
'translation_domain' => $options['translation_domain'],
|
||||
// when compound the array entries are ignored, we need to cascade the configuration here
|
||||
'empty_data' => isset($options['empty_data'][$part]) ? $options['empty_data'][$part] : null,
|
||||
);
|
||||
if ('choice' === $options['widget']) {
|
||||
$childOptions[$part]['choice_translation_domain'] = false;
|
||||
$childOptions[$part]['choices'] = $options[$part];
|
||||
$childOptions[$part]['placeholder'] = $options['placeholder'][$part];
|
||||
$childOptions['choice_translation_domain'] = false;
|
||||
$childOptions['choices'] = $options[$part];
|
||||
$childOptions['placeholder'] = $options['placeholder'][$part];
|
||||
}
|
||||
}
|
||||
}
|
||||
// Append generic carry-along options
|
||||
foreach (array('required', 'translation_domain') as $passOpt) {
|
||||
foreach ($this->timeParts as $part) {
|
||||
if ($options['with_'.$part]) {
|
||||
$childOptions[$part][$passOpt] = $options[$passOpt];
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($this->timeParts as $part) {
|
||||
if ($options['with_'.$part]) {
|
||||
$childForm = $builder->create($part, self::$widgets[$options['widget']], $childOptions[$part]);
|
||||
$childForm = $builder->create($part, self::$widgets[$options['widget']], $childOptions);
|
||||
if ('integer' === $options['widget']) {
|
||||
$childForm->addModelTransformer(
|
||||
new ReversedTransformer(
|
||||
@ -132,7 +124,7 @@ class DateIntervalType extends AbstractType
|
||||
}
|
||||
}
|
||||
if ($options['with_invert']) {
|
||||
$builder->add('invert', 'Symfony\Component\Form\Extension\Core\Type\CheckboxType', array(
|
||||
$builder->add('invert', CheckboxType::class, array(
|
||||
'label' => $options['labels']['invert'],
|
||||
'error_bubbling' => true,
|
||||
'required' => false,
|
||||
@ -180,6 +172,9 @@ class DateIntervalType extends AbstractType
|
||||
$compound = function (Options $options) {
|
||||
return 'single_text' !== $options['widget'];
|
||||
};
|
||||
$emptyData = function (Options $options) {
|
||||
return 'single_text' === $options['widget'] ? '' : array();
|
||||
};
|
||||
|
||||
$placeholderDefault = function (Options $options) {
|
||||
return $options['required'] ? null : '';
|
||||
@ -238,6 +233,7 @@ class DateIntervalType extends AbstractType
|
||||
// this option.
|
||||
'data_class' => null,
|
||||
'compound' => $compound,
|
||||
'empty_data' => $emptyData,
|
||||
'labels' => array(),
|
||||
)
|
||||
);
|
||||
|
@ -48,7 +48,7 @@ class FormValidator extends ConstraintValidator
|
||||
|
||||
// Validate the data against its own constraints
|
||||
if ($form->isRoot() && (\is_object($data) || \is_array($data))) {
|
||||
if (\is_array($groups) && \count($groups) > 0 || $groups instanceof GroupSequence && \count($groups->groups) > 0) {
|
||||
if (($groups && \is_array($groups)) || ($groups instanceof GroupSequence && $groups->groups)) {
|
||||
$validator->atPath('data')->validate($form->getData(), null, $groups);
|
||||
}
|
||||
}
|
||||
|
@ -423,4 +423,32 @@ class DateIntervalTypeTest extends BaseTypeTest
|
||||
$this->assertSame($expectedData, $form->getNormData());
|
||||
$this->assertSame($expectedData, $form->getData());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideEmptyData
|
||||
*/
|
||||
public function testSubmitNullUsesDateEmptyData($widget, $emptyData, $expectedData)
|
||||
{
|
||||
$form = $this->factory->create(static::TESTED_TYPE, null, array(
|
||||
'widget' => $widget,
|
||||
'empty_data' => $emptyData,
|
||||
));
|
||||
$form->submit(null);
|
||||
|
||||
$this->assertSame($emptyData, $form->getViewData());
|
||||
$this->assertEquals($expectedData, $form->getNormData());
|
||||
$this->assertEquals($expectedData, $form->getData());
|
||||
}
|
||||
|
||||
public function provideEmptyData()
|
||||
{
|
||||
$expectedData = \DateInterval::createFromDateString('6 years and 4 months');
|
||||
|
||||
return array(
|
||||
'Simple field' => array('single_text', 'P6Y4M0D', $expectedData),
|
||||
'Compound text field' => array('text', array('years' => '06', 'months' => '04', 'days' => '00'), $expectedData),
|
||||
'Compound integer field' => array('integer', array('years' => '6', 'months' => '4', 'days' => '0'), $expectedData),
|
||||
'Compound choice field' => array('choice', array('years' => '6', 'months' => '4', 'days' => '0'), $expectedData),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ class ExceptionListener implements EventSubscriberInterface
|
||||
* @param \Exception $exception The thrown exception
|
||||
* @param Request $request The original request
|
||||
*
|
||||
* @return Request $request The cloned request
|
||||
* @return Request The cloned request
|
||||
*/
|
||||
protected function duplicateRequest(\Exception $exception, Request $request)
|
||||
{
|
||||
|
@ -93,7 +93,7 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
|
||||
/**
|
||||
* Gets the current store.
|
||||
*
|
||||
* @return StoreInterface $store A StoreInterface instance
|
||||
* @return StoreInterface A StoreInterface instance
|
||||
*/
|
||||
public function getStore()
|
||||
{
|
||||
|
@ -38,7 +38,7 @@ class Entry
|
||||
/**
|
||||
* Returns whether an attribute exists.
|
||||
*
|
||||
* @param $name string The name of the attribute
|
||||
* @param string $name The name of the attribute
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
@ -53,7 +53,7 @@ class Entry
|
||||
* As LDAP can return multiple values for a single attribute,
|
||||
* this value is returned as an array.
|
||||
*
|
||||
* @param $name string The name of the attribute
|
||||
* @param string $name The name of the attribute
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
|
@ -36,8 +36,8 @@ class InputStream implements \IteratorAggregate
|
||||
/**
|
||||
* Appends an input to the write buffer.
|
||||
*
|
||||
* @param resource|string|int|float|bool|\Traversable|null The input to append as scalar,
|
||||
* stream resource or \Traversable
|
||||
* @param resource|string|int|float|bool|\Traversable|null $input The input to append as scalar,
|
||||
* stream resource or \Traversable
|
||||
*/
|
||||
public function write($input)
|
||||
{
|
||||
|
@ -375,7 +375,7 @@ class Router implements RouterInterface, RequestMatcherInterface
|
||||
* Provides the ConfigCache factory implementation, falling back to a
|
||||
* default implementation if necessary.
|
||||
*
|
||||
* @return ConfigCacheFactoryInterface $configCacheFactory
|
||||
* @return ConfigCacheFactoryInterface
|
||||
*/
|
||||
private function getConfigCacheFactory()
|
||||
{
|
||||
|
@ -472,9 +472,6 @@ class PhpMatcherDumperTest extends TestCase
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $dumper
|
||||
*/
|
||||
private function generateDumpedMatcher(RouteCollection $collection, $redirectableStub = false)
|
||||
{
|
||||
$options = array('class' => $this->matcherClass);
|
||||
|
@ -366,7 +366,7 @@ class PhpEngine implements EngineInterface, \ArrayAccess
|
||||
*
|
||||
* @param string $context The context name
|
||||
*
|
||||
* @return callable $escaper A PHP callable
|
||||
* @return callable A PHP callable
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
|
@ -90,7 +90,7 @@ class DataCollectorTranslator implements TranslatorInterface, TranslatorBagInter
|
||||
/**
|
||||
* Gets the fallback locales.
|
||||
*
|
||||
* @return array $locales The fallback locales
|
||||
* @return array The fallback locales
|
||||
*/
|
||||
public function getFallbackLocales()
|
||||
{
|
||||
|
@ -45,7 +45,7 @@ abstract class FileDumper implements DumperInterface
|
||||
/**
|
||||
* Sets backup flag.
|
||||
*
|
||||
* @param bool
|
||||
* @param bool $backup
|
||||
*
|
||||
* @deprecated since Symfony 4.1
|
||||
*/
|
||||
|
@ -89,7 +89,7 @@ class LoggingTranslator implements TranslatorInterface, TranslatorBagInterface
|
||||
/**
|
||||
* Gets the fallback locales.
|
||||
*
|
||||
* @return array $locales The fallback locales
|
||||
* @return array The fallback locales
|
||||
*/
|
||||
public function getFallbackLocales()
|
||||
{
|
||||
|
@ -171,7 +171,7 @@ class Translator implements TranslatorInterface, TranslatorBagInterface
|
||||
/**
|
||||
* Gets the fallback locales.
|
||||
*
|
||||
* @return array $locales The fallback locales
|
||||
* @return array The fallback locales
|
||||
*/
|
||||
public function getFallbackLocales()
|
||||
{
|
||||
|
@ -69,7 +69,7 @@ class ArrayConverter
|
||||
$elem = &$elem[$part];
|
||||
}
|
||||
|
||||
if (\is_array($elem) && \count($elem) > 0 && $parentOfElem) {
|
||||
if ($elem && \is_array($elem) && $parentOfElem) {
|
||||
/* Process next case:
|
||||
* 'foo.bar': 'test1'
|
||||
* 'foo': 'test2'
|
||||
|
@ -120,7 +120,7 @@ abstract class Constraint
|
||||
if (\is_array($options)) {
|
||||
reset($options);
|
||||
}
|
||||
if (\is_array($options) && \count($options) > 0 && \is_string(key($options))) {
|
||||
if ($options && \is_array($options) && \is_string(key($options))) {
|
||||
foreach ($options as $option => $value) {
|
||||
if (array_key_exists($option, $knownOptions)) {
|
||||
$this->$option = $value;
|
||||
|
@ -19,8 +19,8 @@ namespace Symfony\Component\VarDumper\Caster;
|
||||
class ClassStub extends ConstStub
|
||||
{
|
||||
/**
|
||||
* @param string A PHP identifier, e.g. a class, method, interface, etc. name
|
||||
* @param callable The callable targeted by the identifier when it is ambiguous or not a real PHP identifier
|
||||
* @param string $identifier A PHP identifier, e.g. a class, method, interface, etc. name
|
||||
* @param callable $callable The callable targeted by the identifier when it is ambiguous or not a real PHP identifier
|
||||
*/
|
||||
public function __construct(string $identifier, $callable = null)
|
||||
{
|
||||
|
Reference in New Issue
Block a user