Skip to content

[2.2] [Config] Better handling for numerical values: #4714

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 20, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?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
{
/**
* Instantiate a Node
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need a trailing dot.

*
* @return FloatNode The node
*/
protected function instantiateNode()
{
return new FloatNode($this->name, $this->parent, $this->min, $this->max);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?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
{
/**
* Instantiate a Node
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need a trailing dot.

*
* @return IntegerNode The node
*/
protected function instantiateNode()
{
return new IntegerNode($this->name, $this->parent, $this->min, $this->max);
}
}
26 changes: 26 additions & 0 deletions src/Symfony/Component/Config/Definition/Builder/NodeBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ public function __construct()
'variable' => __NAMESPACE__.'\\VariableNodeDefinition',
'scalar' => __NAMESPACE__.'\\ScalarNodeDefinition',
'boolean' => __NAMESPACE__.'\\BooleanNodeDefinition',
'integer' => __NAMESPACE__.'\\IntegerNodeDefinition',
'float' => __NAMESPACE__.'\\FloatNodeDefinition',
'array' => __NAMESPACE__.'\\ArrayNodeDefinition',
'enum' => __NAMESPACE__.'\\EnumNodeDefinition',
);
Expand Down Expand Up @@ -86,6 +88,30 @@ public function booleanNode($name)
return $this->node($name, 'boolean');
}

/**
* Creates a child integer node.
*
* @param string $name the name of the node
*
* @return IntegerNodeDefinition The child node
*/
public function integerNode($name)
{
return $this->node($name, 'integer');
}

/**
* Creates a child float node.
*
* @param string $name the name of the node
*
* @return FloatNodeDefinition The child node
*/
public function floatNode($name)
{
return $this->node($name, 'float');
}

/**
* Creates a child EnumNode.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?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;

/**
* Abstract class that contain common code of integer and float node definition.
*
* @author David Jeanmonod <david.jeanmonod@gmail.com>
*/
abstract class NumericNodeDefinition extends ScalarNodeDefinition
{

protected $min;
protected $max;

/**
* Ensure the value is smaller than the given reference
*
* @param mixed $max
*
* @return NumericNodeDefinition
*/
public function max($max)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing phpdoc for \InvalidArgumentException (same on min).

{
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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing blank line here.

}

/**
* Ensure the value is bigger than the given reference
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need a trailing dot.

*
* @param mixed $min
*
* @return NumericNodeDefinition
*/
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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

}
}
44 changes: 44 additions & 0 deletions src/Symfony/Component/Config/Definition/FloatNode.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?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;

use Symfony\Component\Config\Definition\Exception\InvalidTypeException;

/**
* This node represents a float value in the config tree.
*
* @author Jeanmonod David <david.jeanmonod@gmail.com>
*/
class FloatNode extends NumericNode
{
/**
* {@inheritDoc}
*/
protected function validateType($value)
{
// Integers are also accepted, we just cast them
if (is_int($value)) {
$value = (float) $value;
}

if (!is_float($value)) {
$ex = new InvalidTypeException(sprintf(
'Invalid type for path "%s". Expected float, but got %s.',
$this->getPath(),
gettype($value)
));
$ex->setPath($this->getPath());

throw $ex;
}
}
}
39 changes: 39 additions & 0 deletions src/Symfony/Component/Config/Definition/IntegerNode.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?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;

use Symfony\Component\Config\Definition\Exception\InvalidTypeException;

/**
* This node represents an integer value in the config tree.
*
* @author Jeanmonod David <david.jeanmonod@gmail.com>
*/
class IntegerNode extends NumericNode
{
/**
* {@inheritDoc}
*/
protected function validateType($value)
{
if (!is_int($value)) {
$ex = new InvalidTypeException(sprintf(
'Invalid type for path "%s". Expected int, but got %s.',
$this->getPath(),
gettype($value)
));
$ex->setPath($this->getPath());

throw $ex;
}
}
}
56 changes: 56 additions & 0 deletions src/Symfony/Component/Config/Definition/NumericNode.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?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;

use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;

/**
* This node represents a numeric value in the config tree
*
* @author David Jeanmonod <david.jeanmonod@gmail.com>
*/
class NumericNode extends ScalarNode
{
protected $min;
protected $max;

public function __construct($name, NodeInterface $parent = null, $min = null, $max = null)
{
parent::__construct($name, $parent);
$this->min = $min;
$this->max = $max;
}

/**
* {@inheritDoc}
*/
protected function finalizeValue($value)
{
$value = parent::finalizeValue($value);

$errorMsg = null;
if (isset($this->min) && $value < $this->min) {
$errorMsg = sprintf('The value %s is too small for path "%s". Should be greater than: %s', $value, $this->getPath(), $this->min);
}
if (isset($this->max) && $value > $this->max) {
$errorMsg = sprintf('The value %s is too big for path "%s". Should be less than: %s', $value, $this->getPath(), $this->max);
}
if (isset($errorMsg)) {
$ex = new InvalidConfigurationException($errorMsg);
$ex->setPath($this->getPath());
throw $ex;
}

return $value;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

use Symfony\Component\Config\Definition\Builder\TreeBuilder;


class ExprBuilderTest extends \PHPUnit_Framework_TestCase
{

Expand Down Expand Up @@ -160,6 +159,7 @@ public function testThenUnsetExpression()
protected function getTestBuilder()
{
$builder = new TreeBuilder();

return $builder
->root('test')
->children()
Expand All @@ -171,7 +171,7 @@ protected function getTestBuilder()
/**
* Close the validation process and finalize with the given config
* @param TreeBuilder $testBuilder The tree builder to finalize
* @param array $config The config you want to use for the finalization, if nothing provided
* @param array $config The config you want to use for the finalization, if nothing provided
* a simple array('key'=>'value') will be used
* @return array The finalized config values
*/
Expand All @@ -191,17 +191,18 @@ protected function finalizeTestBuilder($testBuilder, $config=null)
* @param $val The value that the closure must return
* @return Closure
*/
protected function returnClosure($val) {
protected function returnClosure($val)
{
return function($v) use ($val) {
return $val;
};
}

/**
* Assert that the given test builder, will return the given value
* @param mixed $value The value to test
* @param TreeBuilder $test The tree builder to finalize
* @param mixed $config The config values that new to be finalized
* @param mixed $value The value to test
* @param TreeBuilder $test The tree builder to finalize
* @param mixed $config The config values that new to be finalized
*/
protected function assertFinalizedValueIs($value, $treeBuilder, $config=null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,17 @@ public function testNodeTypesAreNotCaseSensitive()

$this->assertEquals(get_class($node1), get_class($node2));
}

public function testNumericNodeCreation()
{
$builder = new NodeBuilder();

$node = $builder->integerNode('foo')->min(3)->max(5);
$this->assertEquals('Symfony\Component\Config\Definition\Builder\IntegerNodeDefinition', get_class($node));

$node = $builder->floatNode('bar')->min(3.0)->max(5.0);
$this->assertEquals('Symfony\Component\Config\Definition\Builder\FloatNodeDefinition', get_class($node));
}
}

class SomeNodeDefinition extends BaseVariableNodeDefinition
Expand Down
Loading