Update website

This commit is contained in:
Guilhem Lavaux 2024-11-19 09:35:33 +01:00
parent bb4b0f9be8
commit 011b183e28
4263 changed files with 3014 additions and 720369 deletions

View file

@ -1,549 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Config\Definition\Builder;
use Symfony\Component\Config\Definition\ArrayNode;
use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException;
use Symfony\Component\Config\Definition\PrototypedArrayNode;
/**
* This class provides a fluent interface for defining an array node.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinitionInterface
{
protected $performDeepMerging = true;
protected $ignoreExtraKeys = false;
protected $removeExtraKeys = true;
protected $children = [];
protected $prototype;
protected $atLeastOne = false;
protected $allowNewKeys = true;
protected $key;
protected $removeKeyItem;
protected $addDefaults = false;
protected $addDefaultChildren = false;
protected $nodeBuilder;
protected $normalizeKeys = true;
/**
* {@inheritdoc}
*/
public function __construct(?string $name, NodeParentInterface $parent = null)
{
parent::__construct($name, $parent);
$this->nullEquivalent = [];
$this->trueEquivalent = [];
}
/**
* {@inheritdoc}
*/
public function setBuilder(NodeBuilder $builder)
{
$this->nodeBuilder = $builder;
}
/**
* {@inheritdoc}
*/
public function children()
{
return $this->getNodeBuilder();
}
/**
* Sets a prototype for child nodes.
*
* @return NodeDefinition
*/
public function prototype(string $type)
{
return $this->prototype = $this->getNodeBuilder()->node(null, $type)->setParent($this);
}
/**
* @return VariableNodeDefinition
*/
public function variablePrototype()
{
return $this->prototype('variable');
}
/**
* @return ScalarNodeDefinition
*/
public function scalarPrototype()
{
return $this->prototype('scalar');
}
/**
* @return BooleanNodeDefinition
*/
public function booleanPrototype()
{
return $this->prototype('boolean');
}
/**
* @return IntegerNodeDefinition
*/
public function integerPrototype()
{
return $this->prototype('integer');
}
/**
* @return FloatNodeDefinition
*/
public function floatPrototype()
{
return $this->prototype('float');
}
/**
* @return ArrayNodeDefinition
*/
public function arrayPrototype()
{
return $this->prototype('array');
}
/**
* @return EnumNodeDefinition
*/
public function enumPrototype()
{
return $this->prototype('enum');
}
/**
* Adds the default value if the node is not set in the configuration.
*
* This method is applicable to concrete nodes only (not to prototype nodes).
* If this function has been called and the node is not set during the finalization
* phase, it's default value will be derived from its children default values.
*
* @return $this
*/
public function addDefaultsIfNotSet()
{
$this->addDefaults = true;
return $this;
}
/**
* Adds children with a default value when none are defined.
*
* This method is applicable to prototype nodes only.
*
* @param int|string|array|null $children The number of children|The child name|The children names to be added
*
* @return $this
*/
public function addDefaultChildrenIfNoneSet($children = null)
{
$this->addDefaultChildren = $children;
return $this;
}
/**
* Requires the node to have at least one element.
*
* This method is applicable to prototype nodes only.
*
* @return $this
*/
public function requiresAtLeastOneElement()
{
$this->atLeastOne = true;
return $this;
}
/**
* Disallows adding news keys in a subsequent configuration.
*
* If used all keys have to be defined in the same configuration file.
*
* @return $this
*/
public function disallowNewKeysInSubsequentConfigs()
{
$this->allowNewKeys = false;
return $this;
}
/**
* Sets a normalization rule for XML configurations.
*
* @param string $singular The key to remap
* @param string|null $plural The plural of the key for irregular plurals
*
* @return $this
*/
public function fixXmlConfig(string $singular, string $plural = null)
{
$this->normalization()->remap($singular, $plural);
return $this;
}
/**
* Sets the attribute which value is to be used as key.
*
* This is useful when you have an indexed array that should be an
* associative array. You can select an item from within the array
* to be the key of the particular item. For example, if "id" is the
* "key", then:
*
* [
* ['id' => 'my_name', 'foo' => 'bar'],
* ];
*
* becomes
*
* [
* 'my_name' => ['foo' => 'bar'],
* ];
*
* If you'd like "'id' => 'my_name'" to still be present in the resulting
* array, then you can set the second argument of this method to false.
*
* This method is applicable to prototype nodes only.
*
* @param string $name The name of the key
* @param bool $removeKeyItem Whether or not the key item should be removed
*
* @return $this
*/
public function useAttributeAsKey(string $name, bool $removeKeyItem = true)
{
$this->key = $name;
$this->removeKeyItem = $removeKeyItem;
return $this;
}
/**
* Sets whether the node can be unset.
*
* @return $this
*/
public function canBeUnset(bool $allow = true)
{
$this->merge()->allowUnset($allow);
return $this;
}
/**
* Adds an "enabled" boolean to enable the current section.
*
* By default, the section is disabled. If any configuration is specified then
* the node will be automatically enabled:
*
* enableableArrayNode: {enabled: true, ...} # The config is enabled & default values get overridden
* enableableArrayNode: ~ # The config is enabled & use the default values
* enableableArrayNode: true # The config is enabled & use the default values
* enableableArrayNode: {other: value, ...} # The config is enabled & default values get overridden
* enableableArrayNode: {enabled: false, ...} # The config is disabled
* enableableArrayNode: false # The config is disabled
*
* @return $this
*/
public function canBeEnabled()
{
$this
->addDefaultsIfNotSet()
->treatFalseLike(['enabled' => false])
->treatTrueLike(['enabled' => true])
->treatNullLike(['enabled' => true])
->beforeNormalization()
->ifArray()
->then(function (array $v) {
$v['enabled'] = $v['enabled'] ?? true;
return $v;
})
->end()
->children()
->booleanNode('enabled')
->defaultFalse()
;
return $this;
}
/**
* Adds an "enabled" boolean to enable the current section.
*
* By default, the section is enabled.
*
* @return $this
*/
public function canBeDisabled()
{
$this
->addDefaultsIfNotSet()
->treatFalseLike(['enabled' => false])
->treatTrueLike(['enabled' => true])
->treatNullLike(['enabled' => true])
->children()
->booleanNode('enabled')
->defaultTrue()
;
return $this;
}
/**
* Disables the deep merging of the node.
*
* @return $this
*/
public function performNoDeepMerging()
{
$this->performDeepMerging = false;
return $this;
}
/**
* Allows extra config keys to be specified under an array without
* throwing an exception.
*
* Those config values are ignored and removed from the resulting
* array. This should be used only in special cases where you want
* to send an entire configuration array through a special tree that
* processes only part of the array.
*
* @param bool $remove Whether to remove the extra keys
*
* @return $this
*/
public function ignoreExtraKeys(bool $remove = true)
{
$this->ignoreExtraKeys = true;
$this->removeExtraKeys = $remove;
return $this;
}
/**
* Sets whether to enable key normalization.
*
* @return $this
*/
public function normalizeKeys(bool $bool)
{
$this->normalizeKeys = $bool;
return $this;
}
/**
* {@inheritdoc}
*/
public function append(NodeDefinition $node)
{
$this->children[$node->name] = $node->setParent($this);
return $this;
}
/**
* Returns a node builder to be used to add children and prototype.
*
* @return NodeBuilder
*/
protected function getNodeBuilder()
{
if (null === $this->nodeBuilder) {
$this->nodeBuilder = new NodeBuilder();
}
return $this->nodeBuilder->setParent($this);
}
/**
* {@inheritdoc}
*/
protected function createNode()
{
if (null === $this->prototype) {
$node = new ArrayNode($this->name, $this->parent, $this->pathSeparator);
$this->validateConcreteNode($node);
$node->setAddIfNotSet($this->addDefaults);
foreach ($this->children as $child) {
$child->parent = $node;
$node->addChild($child->getNode());
}
} else {
$node = new PrototypedArrayNode($this->name, $this->parent, $this->pathSeparator);
$this->validatePrototypeNode($node);
if (null !== $this->key) {
$node->setKeyAttribute($this->key, $this->removeKeyItem);
}
if (true === $this->atLeastOne || false === $this->allowEmptyValue) {
$node->setMinNumberOfElements(1);
}
if ($this->default) {
if (!\is_array($this->defaultValue)) {
throw new \InvalidArgumentException(sprintf('%s: the default value of an array node has to be an array.', $node->getPath()));
}
$node->setDefaultValue($this->defaultValue);
}
if (false !== $this->addDefaultChildren) {
$node->setAddChildrenIfNoneSet($this->addDefaultChildren);
if ($this->prototype instanceof static && null === $this->prototype->prototype) {
$this->prototype->addDefaultsIfNotSet();
}
}
$this->prototype->parent = $node;
$node->setPrototype($this->prototype->getNode());
}
$node->setAllowNewKeys($this->allowNewKeys);
$node->addEquivalentValue(null, $this->nullEquivalent);
$node->addEquivalentValue(true, $this->trueEquivalent);
$node->addEquivalentValue(false, $this->falseEquivalent);
$node->setPerformDeepMerging($this->performDeepMerging);
$node->setRequired($this->required);
$node->setIgnoreExtraKeys($this->ignoreExtraKeys, $this->removeExtraKeys);
$node->setNormalizeKeys($this->normalizeKeys);
if ($this->deprecation) {
$node->setDeprecated($this->deprecation['package'], $this->deprecation['version'], $this->deprecation['message']);
}
if (null !== $this->normalization) {
$node->setNormalizationClosures($this->normalization->before);
$node->setXmlRemappings($this->normalization->remappings);
}
if (null !== $this->merge) {
$node->setAllowOverwrite($this->merge->allowOverwrite);
$node->setAllowFalse($this->merge->allowFalse);
}
if (null !== $this->validation) {
$node->setFinalValidationClosures($this->validation->rules);
}
return $node;
}
/**
* Validate the configuration of a concrete node.
*
* @throws InvalidDefinitionException
*/
protected function validateConcreteNode(ArrayNode $node)
{
$path = $node->getPath();
if (null !== $this->key) {
throw new InvalidDefinitionException(sprintf('->useAttributeAsKey() is not applicable to concrete nodes at path "%s".', $path));
}
if (false === $this->allowEmptyValue) {
throw new InvalidDefinitionException(sprintf('->cannotBeEmpty() is not applicable to concrete nodes at path "%s".', $path));
}
if (true === $this->atLeastOne) {
throw new InvalidDefinitionException(sprintf('->requiresAtLeastOneElement() is not applicable to concrete nodes at path "%s".', $path));
}
if ($this->default) {
throw new InvalidDefinitionException(sprintf('->defaultValue() is not applicable to concrete nodes at path "%s".', $path));
}
if (false !== $this->addDefaultChildren) {
throw new InvalidDefinitionException(sprintf('->addDefaultChildrenIfNoneSet() is not applicable to concrete nodes at path "%s".', $path));
}
}
/**
* Validate the configuration of a prototype node.
*
* @throws InvalidDefinitionException
*/
protected function validatePrototypeNode(PrototypedArrayNode $node)
{
$path = $node->getPath();
if ($this->addDefaults) {
throw new InvalidDefinitionException(sprintf('->addDefaultsIfNotSet() is not applicable to prototype nodes at path "%s".', $path));
}
if (false !== $this->addDefaultChildren) {
if ($this->default) {
throw new InvalidDefinitionException(sprintf('A default value and default children might not be used together at path "%s".', $path));
}
if (null !== $this->key && (null === $this->addDefaultChildren || \is_int($this->addDefaultChildren) && $this->addDefaultChildren > 0)) {
throw new InvalidDefinitionException(sprintf('->addDefaultChildrenIfNoneSet() should set default children names as ->useAttributeAsKey() is used at path "%s".', $path));
}
if (null === $this->key && (\is_string($this->addDefaultChildren) || \is_array($this->addDefaultChildren))) {
throw new InvalidDefinitionException(sprintf('->addDefaultChildrenIfNoneSet() might not set default children names as ->useAttributeAsKey() is not used at path "%s".', $path));
}
}
}
/**
* @return NodeDefinition[]
*/
public function getChildNodeDefinitions()
{
return $this->children;
}
/**
* Finds a node defined by the given $nodePath.
*
* @param string $nodePath The path of the node to find. e.g "doctrine.orm.mappings"
*/
public function find(string $nodePath): NodeDefinition
{
$firstPathSegment = (false === $pathSeparatorPos = strpos($nodePath, $this->pathSeparator))
? $nodePath
: substr($nodePath, 0, $pathSeparatorPos);
if (null === $node = ($this->children[$firstPathSegment] ?? null)) {
throw new \RuntimeException(sprintf('Node with name "%s" does not exist in the current node "%s".', $firstPathSegment, $this->name));
}
if (false === $pathSeparatorPos) {
return $node;
}
return $node->find(substr($nodePath, $pathSeparatorPos + \strlen($this->pathSeparator)));
}
}

View file

@ -1,53 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Config\Definition\Builder;
use Symfony\Component\Config\Definition\BooleanNode;
use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException;
/**
* This class provides a fluent interface for defining a node.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class BooleanNodeDefinition extends ScalarNodeDefinition
{
/**
* {@inheritdoc}
*/
public function __construct(?string $name, NodeParentInterface $parent = null)
{
parent::__construct($name, $parent);
$this->nullEquivalent = true;
}
/**
* Instantiate a Node.
*
* @return BooleanNode
*/
protected function instantiateNode()
{
return new BooleanNode($this->name, $this->parent, $this->pathSeparator);
}
/**
* {@inheritdoc}
*
* @throws InvalidDefinitionException
*/
public function cannotBeEmpty()
{
throw new InvalidDefinitionException('->cannotBeEmpty() is not applicable to BooleanNodeDefinition.');
}
}

View file

@ -1,25 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Config\Definition\Builder;
/**
* An interface that can be implemented by nodes which build other nodes.
*
* @author Roland Franssen <franssen.roland@gmail.com>
*/
interface BuilderAwareInterface
{
/**
* Sets a custom children builder.
*/
public function setBuilder(NodeBuilder $builder);
}

View file

@ -1,56 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Config\Definition\Builder;
use Symfony\Component\Config\Definition\EnumNode;
/**
* Enum Node Definition.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class EnumNodeDefinition extends ScalarNodeDefinition
{
private $values;
/**
* @return $this
*/
public function values(array $values)
{
$values = array_unique($values);
if (empty($values)) {
throw new \InvalidArgumentException('->values() must be called with at least one value.');
}
$this->values = $values;
return $this;
}
/**
* Instantiate a Node.
*
* @return EnumNode
*
* @throws \RuntimeException
*/
protected function instantiateNode()
{
if (null === $this->values) {
throw new \RuntimeException('You must call ->values() on enum nodes.');
}
return new EnumNode($this->name, $this->parent, $this->values, $this->pathSeparator);
}
}

View file

@ -1,246 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Config\Definition\Builder;
use Symfony\Component\Config\Definition\Exception\UnsetKeyException;
/**
* This class builds an if expression.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
* @author Christophe Coevoet <stof@notk.org>
*/
class ExprBuilder
{
protected $node;
public $ifPart;
public $thenPart;
public function __construct(NodeDefinition $node)
{
$this->node = $node;
}
/**
* Marks the expression as being always used.
*
* @return $this
*/
public function always(\Closure $then = null)
{
$this->ifPart = function () { return true; };
if (null !== $then) {
$this->thenPart = $then;
}
return $this;
}
/**
* Sets a closure to use as tests.
*
* The default one tests if the value is true.
*
* @return $this
*/
public function ifTrue(\Closure $closure = null)
{
if (null === $closure) {
$closure = function ($v) { return true === $v; };
}
$this->ifPart = $closure;
return $this;
}
/**
* Tests if the value is a string.
*
* @return $this
*/
public function ifString()
{
$this->ifPart = function ($v) { return \is_string($v); };
return $this;
}
/**
* Tests if the value is null.
*
* @return $this
*/
public function ifNull()
{
$this->ifPart = function ($v) { return null === $v; };
return $this;
}
/**
* Tests if the value is empty.
*
* @return $this
*/
public function ifEmpty()
{
$this->ifPart = function ($v) { return empty($v); };
return $this;
}
/**
* Tests if the value is an array.
*
* @return $this
*/
public function ifArray()
{
$this->ifPart = function ($v) { return \is_array($v); };
return $this;
}
/**
* Tests if the value is in an array.
*
* @return $this
*/
public function ifInArray(array $array)
{
$this->ifPart = function ($v) use ($array) { return \in_array($v, $array, true); };
return $this;
}
/**
* Tests if the value is not in an array.
*
* @return $this
*/
public function ifNotInArray(array $array)
{
$this->ifPart = function ($v) use ($array) { return !\in_array($v, $array, true); };
return $this;
}
/**
* Transforms variables of any type into an array.
*
* @return $this
*/
public function castToArray()
{
$this->ifPart = function ($v) { return !\is_array($v); };
$this->thenPart = function ($v) { return [$v]; };
return $this;
}
/**
* Sets the closure to run if the test pass.
*
* @return $this
*/
public function then(\Closure $closure)
{
$this->thenPart = $closure;
return $this;
}
/**
* Sets a closure returning an empty array.
*
* @return $this
*/
public function thenEmptyArray()
{
$this->thenPart = function () { return []; };
return $this;
}
/**
* Sets a closure marking the value as invalid at processing time.
*
* if you want to add the value of the node in your message just use a %s placeholder.
*
* @return $this
*
* @throws \InvalidArgumentException
*/
public function thenInvalid(string $message)
{
$this->thenPart = function ($v) use ($message) { throw new \InvalidArgumentException(sprintf($message, json_encode($v))); };
return $this;
}
/**
* Sets a closure unsetting this key of the array at processing time.
*
* @return $this
*
* @throws UnsetKeyException
*/
public function thenUnset()
{
$this->thenPart = function () { throw new UnsetKeyException('Unsetting key.'); };
return $this;
}
/**
* Returns the related node.
*
* @return NodeDefinition|ArrayNodeDefinition|VariableNodeDefinition
*
* @throws \RuntimeException
*/
public function end()
{
if (null === $this->ifPart) {
throw new \RuntimeException('You must specify an if part.');
}
if (null === $this->thenPart) {
throw new \RuntimeException('You must specify a then part.');
}
return $this->node;
}
/**
* Builds the expressions.
*
* @param ExprBuilder[] $expressions An array of ExprBuilder instances to build
*
* @return array
*/
public static function buildExpressions(array $expressions)
{
foreach ($expressions as $k => $expr) {
if ($expr instanceof self) {
$if = $expr->ifPart;
$then = $expr->thenPart;
$expressions[$k] = function ($v) use ($if, $then) {
return $if($v) ? $then($v) : $v;
};
}
}
return $expressions;
}
}

View file

@ -1,32 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Config\Definition\Builder;
use Symfony\Component\Config\Definition\FloatNode;
/**
* This class provides a fluent interface for defining a float node.
*
* @author Jeanmonod David <david.jeanmonod@gmail.com>
*/
class FloatNodeDefinition extends NumericNodeDefinition
{
/**
* Instantiates a Node.
*
* @return FloatNode
*/
protected function instantiateNode()
{
return new FloatNode($this->name, $this->parent, $this->min, $this->max, $this->pathSeparator);
}
}

View file

@ -1,32 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Config\Definition\Builder;
use Symfony\Component\Config\Definition\IntegerNode;
/**
* This class provides a fluent interface for defining an integer node.
*
* @author Jeanmonod David <david.jeanmonod@gmail.com>
*/
class IntegerNodeDefinition extends NumericNodeDefinition
{
/**
* Instantiates a Node.
*
* @return IntegerNode
*/
protected function instantiateNode()
{
return new IntegerNode($this->name, $this->parent, $this->min, $this->max, $this->pathSeparator);
}
}

View file

@ -1,63 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Config\Definition\Builder;
/**
* This class builds merge conditions.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class MergeBuilder
{
protected $node;
public $allowFalse = false;
public $allowOverwrite = true;
public function __construct(NodeDefinition $node)
{
$this->node = $node;
}
/**
* Sets whether the node can be unset.
*
* @return $this
*/
public function allowUnset(bool $allow = true)
{
$this->allowFalse = $allow;
return $this;
}
/**
* Sets whether the node can be overwritten.
*
* @return $this
*/
public function denyOverwrite(bool $deny = true)
{
$this->allowOverwrite = !$deny;
return $this;
}
/**
* Returns the related node.
*
* @return NodeDefinition|ArrayNodeDefinition|VariableNodeDefinition
*/
public function end()
{
return $this->node;
}
}

View file

@ -1,219 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Config\Definition\Builder;
/**
* This class provides a fluent interface for building a node.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class NodeBuilder implements NodeParentInterface
{
protected $parent;
protected $nodeMapping;
public function __construct()
{
$this->nodeMapping = [
'variable' => VariableNodeDefinition::class,
'scalar' => ScalarNodeDefinition::class,
'boolean' => BooleanNodeDefinition::class,
'integer' => IntegerNodeDefinition::class,
'float' => FloatNodeDefinition::class,
'array' => ArrayNodeDefinition::class,
'enum' => EnumNodeDefinition::class,
];
}
/**
* Set the parent node.
*
* @return $this
*/
public function setParent(ParentNodeDefinitionInterface $parent = null)
{
$this->parent = $parent;
return $this;
}
/**
* Creates a child array node.
*
* @return ArrayNodeDefinition
*/
public function arrayNode(string $name)
{
return $this->node($name, 'array');
}
/**
* Creates a child scalar node.
*
* @return ScalarNodeDefinition
*/
public function scalarNode(string $name)
{
return $this->node($name, 'scalar');
}
/**
* Creates a child Boolean node.
*
* @return BooleanNodeDefinition
*/
public function booleanNode(string $name)
{
return $this->node($name, 'boolean');
}
/**
* Creates a child integer node.
*
* @return IntegerNodeDefinition
*/
public function integerNode(string $name)
{
return $this->node($name, 'integer');
}
/**
* Creates a child float node.
*
* @return FloatNodeDefinition
*/
public function floatNode(string $name)
{
return $this->node($name, 'float');
}
/**
* Creates a child EnumNode.
*
* @return EnumNodeDefinition
*/
public function enumNode(string $name)
{
return $this->node($name, 'enum');
}
/**
* Creates a child variable node.
*
* @return VariableNodeDefinition
*/
public function variableNode(string $name)
{
return $this->node($name, 'variable');
}
/**
* Returns the parent node.
*
* @return NodeDefinition&ParentNodeDefinitionInterface
*/
public function end()
{
return $this->parent;
}
/**
* Creates a child node.
*
* @return NodeDefinition
*
* @throws \RuntimeException When the node type is not registered
* @throws \RuntimeException When the node class is not found
*/
public function node(?string $name, string $type)
{
$class = $this->getNodeClass($type);
$node = new $class($name);
$this->append($node);
return $node;
}
/**
* Appends a node definition.
*
* Usage:
*
* $node = new ArrayNodeDefinition('name')
* ->children()
* ->scalarNode('foo')->end()
* ->scalarNode('baz')->end()
* ->append($this->getBarNodeDefinition())
* ->end()
* ;
*
* @return $this
*/
public function append(NodeDefinition $node)
{
if ($node instanceof BuilderAwareInterface) {
$builder = clone $this;
$builder->setParent(null);
$node->setBuilder($builder);
}
if (null !== $this->parent) {
$this->parent->append($node);
// Make this builder the node parent to allow for a fluid interface
$node->setParent($this);
}
return $this;
}
/**
* Adds or overrides a node Type.
*
* @param string $type The name of the type
* @param string $class The fully qualified name the node definition class
*
* @return $this
*/
public function setNodeClass(string $type, string $class)
{
$this->nodeMapping[strtolower($type)] = $class;
return $this;
}
/**
* Returns the class name of the node definition.
*
* @return string
*
* @throws \RuntimeException When the node type is not registered
* @throws \RuntimeException When the node class is not found
*/
protected function getNodeClass(string $type)
{
$type = strtolower($type);
if (!isset($this->nodeMapping[$type])) {
throw new \RuntimeException(sprintf('The node type "%s" is not registered.', $type));
}
$class = $this->nodeMapping[$type];
if (!class_exists($class)) {
throw new \RuntimeException(sprintf('The node class "%s" does not exist.', $class));
}
return $class;
}
}

View file

@ -1,383 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Config\Definition\Builder;
use Symfony\Component\Config\Definition\BaseNode;
use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException;
use Symfony\Component\Config\Definition\NodeInterface;
/**
* This class provides a fluent interface for defining a node.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
abstract class NodeDefinition implements NodeParentInterface
{
protected $name;
protected $normalization;
protected $validation;
protected $defaultValue;
protected $default = false;
protected $required = false;
protected $deprecation = [];
protected $merge;
protected $allowEmptyValue = true;
protected $nullEquivalent;
protected $trueEquivalent = true;
protected $falseEquivalent = false;
protected $pathSeparator = BaseNode::DEFAULT_PATH_SEPARATOR;
protected $parent;
protected $attributes = [];
public function __construct(?string $name, NodeParentInterface $parent = null)
{
$this->parent = $parent;
$this->name = $name;
}
/**
* Sets the parent node.
*
* @return $this
*/
public function setParent(NodeParentInterface $parent)
{
$this->parent = $parent;
return $this;
}
/**
* Sets info message.
*
* @return $this
*/
public function info(string $info)
{
return $this->attribute('info', $info);
}
/**
* Sets example configuration.
*
* @param string|array $example
*
* @return $this
*/
public function example($example)
{
return $this->attribute('example', $example);
}
/**
* Sets an attribute on the node.
*
* @param mixed $value
*
* @return $this
*/
public function attribute(string $key, $value)
{
$this->attributes[$key] = $value;
return $this;
}
/**
* Returns the parent node.
*
* @return NodeParentInterface|NodeBuilder|NodeDefinition|ArrayNodeDefinition|VariableNodeDefinition|null
*/
public function end()
{
return $this->parent;
}
/**
* Creates the node.
*
* @return NodeInterface
*/
public function getNode(bool $forceRootNode = false)
{
if ($forceRootNode) {
$this->parent = null;
}
if (null !== $this->normalization) {
$this->normalization->before = ExprBuilder::buildExpressions($this->normalization->before);
}
if (null !== $this->validation) {
$this->validation->rules = ExprBuilder::buildExpressions($this->validation->rules);
}
$node = $this->createNode();
if ($node instanceof BaseNode) {
$node->setAttributes($this->attributes);
}
return $node;
}
/**
* Sets the default value.
*
* @param mixed $value The default value
*
* @return $this
*/
public function defaultValue($value)
{
$this->default = true;
$this->defaultValue = $value;
return $this;
}
/**
* Sets the node as required.
*
* @return $this
*/
public function isRequired()
{
$this->required = true;
return $this;
}
/**
* Sets the node as deprecated.
*
* @param string $package The name of the composer package that is triggering the deprecation
* @param string $version The version of the package that introduced the deprecation
* @param string $message the deprecation message to use
*
* You can use %node% and %path% placeholders in your message to display,
* respectively, the node name and its complete path
*
* @return $this
*/
public function setDeprecated(/* string $package, string $version, string $message = 'The child node "%node%" at path "%path%" is deprecated.' */)
{
$args = \func_get_args();
if (\func_num_args() < 2) {
trigger_deprecation('symfony/config', '5.1', 'The signature of method "%s()" requires 3 arguments: "string $package, string $version, string $message", not defining them is deprecated.', __METHOD__);
$message = $args[0] ?? 'The child node "%node%" at path "%path%" is deprecated.';
$package = $version = '';
} else {
$package = (string) $args[0];
$version = (string) $args[1];
$message = (string) ($args[2] ?? 'The child node "%node%" at path "%path%" is deprecated.');
}
$this->deprecation = [
'package' => $package,
'version' => $version,
'message' => $message,
];
return $this;
}
/**
* Sets the equivalent value used when the node contains null.
*
* @param mixed $value
*
* @return $this
*/
public function treatNullLike($value)
{
$this->nullEquivalent = $value;
return $this;
}
/**
* Sets the equivalent value used when the node contains true.
*
* @param mixed $value
*
* @return $this
*/
public function treatTrueLike($value)
{
$this->trueEquivalent = $value;
return $this;
}
/**
* Sets the equivalent value used when the node contains false.
*
* @param mixed $value
*
* @return $this
*/
public function treatFalseLike($value)
{
$this->falseEquivalent = $value;
return $this;
}
/**
* Sets null as the default value.
*
* @return $this
*/
public function defaultNull()
{
return $this->defaultValue(null);
}
/**
* Sets true as the default value.
*
* @return $this
*/
public function defaultTrue()
{
return $this->defaultValue(true);
}
/**
* Sets false as the default value.
*
* @return $this
*/
public function defaultFalse()
{
return $this->defaultValue(false);
}
/**
* Sets an expression to run before the normalization.
*
* @return ExprBuilder
*/
public function beforeNormalization()
{
return $this->normalization()->before();
}
/**
* Denies the node value being empty.
*
* @return $this
*/
public function cannotBeEmpty()
{
$this->allowEmptyValue = false;
return $this;
}
/**
* Sets an expression to run for the validation.
*
* The expression receives the value of the node and must return it. It can
* modify it.
* An exception should be thrown when the node is not valid.
*
* @return ExprBuilder
*/
public function validate()
{
return $this->validation()->rule();
}
/**
* Sets whether the node can be overwritten.
*
* @return $this
*/
public function cannotBeOverwritten(bool $deny = true)
{
$this->merge()->denyOverwrite($deny);
return $this;
}
/**
* Gets the builder for validation rules.
*
* @return ValidationBuilder
*/
protected function validation()
{
if (null === $this->validation) {
$this->validation = new ValidationBuilder($this);
}
return $this->validation;
}
/**
* Gets the builder for merging rules.
*
* @return MergeBuilder
*/
protected function merge()
{
if (null === $this->merge) {
$this->merge = new MergeBuilder($this);
}
return $this->merge;
}
/**
* Gets the builder for normalization rules.
*
* @return NormalizationBuilder
*/
protected function normalization()
{
if (null === $this->normalization) {
$this->normalization = new NormalizationBuilder($this);
}
return $this->normalization;
}
/**
* Instantiate and configure the node according to this definition.
*
* @return NodeInterface
*
* @throws InvalidDefinitionException When the definition is invalid
*/
abstract protected function createNode();
/**
* Set PathSeparator to use.
*
* @return $this
*/
public function setPathSeparator(string $separator)
{
if ($this instanceof ParentNodeDefinitionInterface) {
foreach ($this->getChildNodeDefinitions() as $child) {
$child->setPathSeparator($separator);
}
}
$this->pathSeparator = $separator;
return $this;
}
}

View file

@ -1,21 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Config\Definition\Builder;
/**
* An interface that must be implemented by all node parents.
*
* @author Victor Berchet <victor@suumit.com>
*/
interface NodeParentInterface
{
}

View file

@ -1,60 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Config\Definition\Builder;
/**
* This class builds normalization conditions.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class NormalizationBuilder
{
protected $node;
public $before = [];
public $remappings = [];
public function __construct(NodeDefinition $node)
{
$this->node = $node;
}
/**
* Registers a key to remap to its plural form.
*
* @param string $key The key to remap
* @param string|null $plural The plural of the key in case of irregular plural
*
* @return $this
*/
public function remap(string $key, string $plural = null)
{
$this->remappings[] = [$key, null === $plural ? $key.'s' : $plural];
return $this;
}
/**
* Registers a closure to run before the normalization or an expression builder to build it if null is provided.
*
* @return ExprBuilder|$this
*/
public function before(\Closure $closure = null)
{
if (null !== $closure) {
$this->before[] = $closure;
return $this;
}
return $this->before[] = new ExprBuilder($this->node);
}
}

View file

@ -1,73 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Config\Definition\Builder;
use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException;
/**
* Abstract class that contains common code of integer and float node definitions.
*
* @author David Jeanmonod <david.jeanmonod@gmail.com>
*/
abstract class NumericNodeDefinition extends ScalarNodeDefinition
{
protected $min;
protected $max;
/**
* Ensures that the value is smaller than the given reference.
*
* @param int|float $max
*
* @return $this
*
* @throws \InvalidArgumentException when the constraint is inconsistent
*/
public function max($max)
{
if (isset($this->min) && $this->min > $max) {
throw new \InvalidArgumentException(sprintf('You cannot define a max(%s) as you already have a min(%s).', $max, $this->min));
}
$this->max = $max;
return $this;
}
/**
* Ensures that the value is bigger than the given reference.
*
* @param int|float $min
*
* @return $this
*
* @throws \InvalidArgumentException when the constraint is inconsistent
*/
public function min($min)
{
if (isset($this->max) && $this->max < $min) {
throw new \InvalidArgumentException(sprintf('You cannot define a min(%s) as you already have a max(%s).', $min, $this->max));
}
$this->min = $min;
return $this;
}
/**
* {@inheritdoc}
*
* @throws InvalidDefinitionException
*/
public function cannotBeEmpty()
{
throw new InvalidDefinitionException('->cannotBeEmpty() is not applicable to NumericNodeDefinition.');
}
}

View file

@ -1,51 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Config\Definition\Builder;
/**
* An interface that must be implemented by nodes which can have children.
*
* @author Victor Berchet <victor@suumit.com>
*/
interface ParentNodeDefinitionInterface extends BuilderAwareInterface
{
/**
* Returns a builder to add children nodes.
*
* @return NodeBuilder
*/
public function children();
/**
* Appends a node definition.
*
* Usage:
*
* $node = $parentNode
* ->children()
* ->scalarNode('foo')->end()
* ->scalarNode('baz')->end()
* ->append($this->getBarNodeDefinition())
* ->end()
* ;
*
* @return $this
*/
public function append(NodeDefinition $node);
/**
* Gets the child node definitions.
*
* @return NodeDefinition[]
*/
public function getChildNodeDefinitions();
}

View file

@ -1,32 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Config\Definition\Builder;
use Symfony\Component\Config\Definition\ScalarNode;
/**
* This class provides a fluent interface for defining a node.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class ScalarNodeDefinition extends VariableNodeDefinition
{
/**
* Instantiate a Node.
*
* @return ScalarNode
*/
protected function instantiateNode()
{
return new ScalarNode($this->name, $this->parent, $this->pathSeparator);
}
}

View file

@ -1,63 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Config\Definition\Builder;
use Symfony\Component\Config\Definition\NodeInterface;
/**
* This is the entry class for building a config tree.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class TreeBuilder implements NodeParentInterface
{
protected $tree;
protected $root;
public function __construct(string $name, string $type = 'array', NodeBuilder $builder = null)
{
$builder = $builder ?? new NodeBuilder();
$this->root = $builder->node($name, $type)->setParent($this);
}
/**
* @return NodeDefinition|ArrayNodeDefinition The root node (as an ArrayNodeDefinition when the type is 'array')
*/
public function getRootNode(): NodeDefinition
{
return $this->root;
}
/**
* Builds the tree.
*
* @return NodeInterface
*
* @throws \RuntimeException
*/
public function buildTree()
{
if (null !== $this->tree) {
return $this->tree;
}
return $this->tree = $this->root->getNode(true);
}
public function setPathSeparator(string $separator)
{
// unset last built as changing path separator changes all nodes
$this->tree = null;
$this->root->setPathSeparator($separator);
}
}

View file

@ -1,44 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Config\Definition\Builder;
/**
* This class builds validation conditions.
*
* @author Christophe Coevoet <stof@notk.org>
*/
class ValidationBuilder
{
protected $node;
public $rules = [];
public function __construct(NodeDefinition $node)
{
$this->node = $node;
}
/**
* Registers a closure to run as normalization or an expression builder to build it if null is provided.
*
* @return ExprBuilder|$this
*/
public function rule(\Closure $closure = null)
{
if (null !== $closure) {
$this->rules[] = $closure;
return $this;
}
return $this->rules[] = new ExprBuilder($this->node);
}
}

View file

@ -1,68 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Config\Definition\Builder;
use Symfony\Component\Config\Definition\VariableNode;
/**
* This class provides a fluent interface for defining a node.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class VariableNodeDefinition extends NodeDefinition
{
/**
* Instantiate a Node.
*
* @return VariableNode
*/
protected function instantiateNode()
{
return new VariableNode($this->name, $this->parent, $this->pathSeparator);
}
/**
* {@inheritdoc}
*/
protected function createNode()
{
$node = $this->instantiateNode();
if (null !== $this->normalization) {
$node->setNormalizationClosures($this->normalization->before);
}
if (null !== $this->merge) {
$node->setAllowOverwrite($this->merge->allowOverwrite);
}
if (true === $this->default) {
$node->setDefaultValue($this->defaultValue);
}
$node->setAllowEmptyValue($this->allowEmptyValue);
$node->addEquivalentValue(null, $this->nullEquivalent);
$node->addEquivalentValue(true, $this->trueEquivalent);
$node->addEquivalentValue(false, $this->falseEquivalent);
$node->setRequired($this->required);
if ($this->deprecation) {
$node->setDeprecated($this->deprecation['package'], $this->deprecation['version'], $this->deprecation['message']);
}
if (null !== $this->validation) {
$node->setFinalValidationClosures($this->validation->rules);
}
return $node;
}
}