Reputation: 48477
my_bundle:
algorithm: blowfish # One of 'md5', 'blowfish', 'sha256', 'sha512'
This configuration is done by this configuration tree:
// Algorithms and constants to check
$algorithms = array(
'md5' => 'CRYPT_MD5',
'blowfish' => 'CRYPT_BLOWFISH',
'sha256' => 'CRYPT_SHA256',
'sha512' => 'CRYPT_SHA512',
);
$rootNode
->children()
->scalarNode('algorithm')
->isRequired()
->beforeNormalization()
->ifString()
->then(function($v) { return strtolower($v); })
->end()
->validate()
->ifNotInArray(array_keys($algorithms))
->thenInvalid('invalid algorithm.')
->end()
->validate()
->ifTrue(function($v) use($algorithms) {
return 1 != @constant($algorithms[$v]);
})
->thenInvalid('algorithm %s is not supported by this system.')
->end()
->end()
->end();
Since each algorithm requires different parameters, how can I dynamically add them as children of the root node, base on the selected algorithm?
For example, if algorithm is "blowfish" there should be a scalar node named "cost", while if "sha512" a scalar node "rounds", each with different validation rules.
EDIT: what I really need is figure out the current algorithm (how to do with $rootNode
?) and than call on of:
$rootNode->append($this->getBlowfishParamsNode());
$rootNode->append($this->getSha256ParamsNode());
$rootNode->append($this->getSha512ParamsNode());
EDIT: possible configurations I'd like to accomplish:
my_bundle:
algorithm: blowfish
cost: 15
Another:
my_bundle:
algorithm: sha512
rounds: 50000
And another:
my_bundle:
algorithm: md5
Upvotes: 15
Views: 1874
Reputation: 31959
You could check (using ifTrue()
) if the value of algorithm
is md5
. If this is the case, you unset the blowfish
, sha256
, sha513
keys in the array containing the raw config values.
You can then use a similar logic if algorithm
is blowfish
, sha256
or sha513
.
$rootNode->
->beforeNormalization()
//...
->ifTrue(function($v) {
// $v contains the raw configuration values
return 'md5' === $v['algorithm'];
})
->then(function($v) {
unset($v['blowfish']);
unset($v['sha256']);
unset($v['sha512']);
return $v;
})
->end()
// ...do same logic for the others
->end();
You'd have to use something like this:
my_bundle:
algorithm: blowfish
md5: #your params
blowfish: #will be unset if algorithm is md5 for example
sha256: #will be unset if algorithm is md5 for example
sha512: #will be unset if algorithm is md5 for example
As you mention, you can then append all of them:
$rootNode->append($this->getMd5ParamsNode());
$rootNode->append($this->getBlowfishParamsNode());
$rootNode->append($this->getSha256ParamsNode());
$rootNode->append($this->getSha512ParamsNode());
There is also a thenUnset()
function.
Doctrine's way of doing it might be of interest here.
Upvotes: 3
Reputation: 360
Gremo, maybe im on the wrong track here. BTW, thanks for your reply on my question.
Its just an opinion maybe its just a silly answer... well here we go.
For your answer i know that you already know/understand how a bundle extension works.
Maybe you can define the 4 empty params needed as seen on configuring-services-and-setting-parameters
...you'll set this parameter in your extension class, based on the incoming configuration values...
Then you can have specific checks on the tree (like if algorithm is 'blowfish' then cost is required)
$rootNode->
->beforeNormalization()
->ifTrue(function($v) {
// $v contains the raw configuration values
// if 'algorithm' blowfish -> cost isRequired
// or as you said on your question you can call
// ->append($this->addBlowfishParametersNode())
})
->then(function($v) {
// maybe some unsetting, but not needed
})
->end()
->children()
// ...
->end()
;
Check "Appending Sections"
public function addBlowfishParametersNode()
{
$builder = new TreeBuilder();
$node = $builder->root('parameters');
$node
->isRequired()
->requiresAtLeastOneElement()
...
...
Upvotes: 0