Skip to content
Draft
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
Expand Up @@ -506,6 +506,7 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode): void
->end()
->arrayNode('metadata')
->normalizeKeys(false)
->useAttributeAsKey('key')
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@stof Adding the useAttributeAsKey would allow us to set specific metadata by key when using the config builder.
But we'd lose out on the ability to set all metadata in 1 call if we already created an instance of the parent node builder.

This is due to the generated config changing from

    /**
     * @param ParamConfigurator|list<ParamConfigurator|mixed> $value
     *
     * @return $this
     */
    public function metadata(ParamConfigurator|array $value): static
    {
        $this->_usedProperties['metadata'] = true;
        $this->metadata = $value;
    
        return $this;
    }

To

    /**
     * @return $this
     */
    public function metadata(string $key, mixed $value): static
    {
        $this->_usedProperties['metadata'] = true;
        $this->metadata[$key] = $value;

        return $this;
    }

Would a breaking change like this be a problem for a bugfix? (cc @nicolas-grekas )

As a sidenote, a update to the workflow docs would also be required in the case we would want to perform these changes.
As it shows some examples for the php configs setting the metadata as an array. And we would lose this option.

    $pullRequest->place()
        ->name('review')
        ->metadata(['description' => 'Human review']);
    $pullRequest->place()->name('merged');
    $pullRequest->place()
        ->name('closed')
        ->metadata(['bg_color' => 'DeepSkyBlue',]);

The XML config in general seems to be broken when parsing though. The example showed on the doc page shows nodes, that should actually be attributes.

But having a combination of place nodes, with and without metadata seems to actually break when using XML config, due to the callbacks used in the beforeNormalization possibly not accounting properly for the differences in data structure of the passed $places var, depending on the type of config used :(

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Small example of the data contained in the $places argument of the normalization callback, when using the example configs from the docs:

PHP
^ array:6 [
  0 => array:1 [
    "name" => "start"
  ]
  1 => array:1 [
    "name" => "coding"
  ]
  2 => array:1 [
    "name" => "test"
  ]
  3 => array:2 [
    "name" => "review"
    "metadata" => array:1 [
      "description" => "Human review"
    ]
  ]
  4 => array:1 [
    "name" => "merged"
  ]
  5 => array:2 [
    "name" => "closed"
    "metadata" => array:1 [
      "bg_color" => "DeepSkyBlue"
    ]
  ]
]
^ array:6 [
 
YAML
^ array:6 [
  "start" => null
  "coding" => null
  "test" => null
  "review" => array:1 [
    "metadata" => array:1 [
      "description" => "Human review"
    ]
  ]
  "merged" => null
  "closed" => array:1 [
    "metadata" => array:1 [
      "bg_color" => "DeepSkyBlue"
    ]
  ]
]
 
# XML
^ array:6 [
  0 => "start"
  1 => "coding"
  2 => "test"
  3 => array:2 [
    "name" => "review"
    "metadata" => array:2 [
      "description" => "Human review"
      "other_value" => "Some other value"
    ]
  ]
  4 => "merged"
  5 => array:2 [
    "name" => "closed"
    "metadata" => array:1 [
      "bg_color" => "DeepSkyBlue"
    ]
  ]
]

Copy link
Member

Choose a reason for hiding this comment

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

Would a breaking change like this be a problem for a bugfix? (cc @nicolas-grekas )

it would yes, since that'd break existing configs

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Mhm, that does create an issue then tbh. As i'm not really sure how to fix the return type, if we cannot add the useAttributeAsKey, seeing how the normalizeKeys was not a preferable way to detect the difference.

Adding a new option we could set to indicate a list or array kinda feels like a bandaid fix, tiptoeing around the problem that the config might just be incorrectly defined to begin with.

I also don't see a clear way to mark methods generated by the builder as deprecated. So we could replace it in the next major. Atleast not without deprecating the entire node, which i don't want, as we still want the node, but differently configured :/

->defaultValue([])
->example(['color' => 'blue', 'description' => 'Workflow to manage article.'])
->prototype('variable')
Expand Down Expand Up @@ -573,6 +574,7 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode): void
->end()
->arrayNode('metadata')
->normalizeKeys(false)
->useAttributeAsKey('key')
->defaultValue([])
->example(['color' => 'blue', 'description' => 'Workflow to manage article.'])
->prototype('variable')
Expand All @@ -583,6 +585,7 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode): void
->end()
->arrayNode('metadata')
->normalizeKeys(false)
->useAttributeAsKey('key')
->defaultValue([])
->example(['color' => 'blue', 'description' => 'Workflow to manage article.'])
->prototype('variable')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,11 @@
$config->transports('foo')->dsn('bar');
$config->transports('bar', ['dsn' => 'foobar']);

$placeConfig = $config->places()->name('foo');
$placeConfig->metadata('key', 'value');
$placeConfig->metadata('key2', ['some_other_value', true]);

$config->places(['name' => 'bar', 'metadata' => ['some' => 'metadata']]);

$config->errorPages()->withTrace(false);
};
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,23 @@
],
'error_pages' => [
'with_trace' => false,
]
],
'places' => [
[
'name' => 'foo',
'metadata' => [
'key' => 'value',
'key2' => [
'some_other_value',
true,
],
],
],
[
'name' => 'bar',
'metadata' => [
'some' => 'metadata',
],
],
],
];
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,24 @@ public function getConfigTreeBuilder(): TreeBuilder
->booleanNode('with_trace')->end()
->end()
->end()
->arrayNode('places')
->requiresAtLeastOneElement()
->prototype('array')
->children()
->scalarNode('name')
->isRequired()
->cannotBeEmpty()
->end()
->arrayNode('metadata')
->normalizeKeys(false)
->useAttributeAsKey('key')
->defaultValue([])
->example(['color' => 'blue', 'description' => 'Workflow to manage article.'])
->prototype('variable')->end()
->end()
->end()
->end()
->end()
->end();

return $tb;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php

namespace Symfony\Config\ArrayValues;

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

/**
* This class is automatically generated to help in creating a config.
*/
class PlacesConfig
{
private $name;
private $metadata;
private $_usedProperties = [];

/**
* @default null
* @param ParamConfigurator|mixed $value
* @return $this
*/
public function name($value): static
{
$this->_usedProperties['name'] = true;
$this->name = $value;

return $this;
}

/**
* @return $this
*/
public function metadata(string $key, mixed $value): static
{
$this->_usedProperties['metadata'] = true;
$this->metadata[$key] = $value;

return $this;
}

public function __construct(array $value = [])
{
if (array_key_exists('name', $value)) {
$this->_usedProperties['name'] = true;
$this->name = $value['name'];
unset($value['name']);
}

if (array_key_exists('metadata', $value)) {
$this->_usedProperties['metadata'] = true;
$this->metadata = $value['metadata'];
unset($value['metadata']);
}

if ([] !== $value) {
throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__).implode(', ', array_keys($value)));
}
}

public function toArray(): array
{
$output = [];
if (isset($this->_usedProperties['name'])) {
$output['name'] = $this->name;
}
if (isset($this->_usedProperties['metadata'])) {
$output['metadata'] = $this->metadata;
}

return $output;
}

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

require_once __DIR__.\DIRECTORY_SEPARATOR.'ArrayValues'.\DIRECTORY_SEPARATOR.'TransportsConfig.php';
require_once __DIR__.\DIRECTORY_SEPARATOR.'ArrayValues'.\DIRECTORY_SEPARATOR.'ErrorPagesConfig.php';
require_once __DIR__.\DIRECTORY_SEPARATOR.'ArrayValues'.\DIRECTORY_SEPARATOR.'PlacesConfig.php';

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

Expand All @@ -14,6 +15,7 @@ class ArrayValuesConfig implements \Symfony\Component\Config\Builder\ConfigBuild
{
private $transports;
private $errorPages;
private $places;
private $_usedProperties = [];

/**
Expand Down Expand Up @@ -56,6 +58,13 @@ public function errorPages(array $value = []): \Symfony\Config\ArrayValues\Error
return $this->errorPages;
}

public function places(array $value = []): \Symfony\Config\ArrayValues\PlacesConfig
{
$this->_usedProperties['places'] = true;

return $this->places[] = new \Symfony\Config\ArrayValues\PlacesConfig($value);
}

public function getExtensionAlias(): string
{
return 'array_values';
Expand All @@ -75,6 +84,12 @@ public function __construct(array $value = [])
unset($value['error_pages']);
}

if (array_key_exists('places', $value)) {
$this->_usedProperties['places'] = true;
$this->places = array_map(fn ($v) => new \Symfony\Config\ArrayValues\PlacesConfig($v), $value['places']);
unset($value['places']);
}

if ([] !== $value) {
throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__).implode(', ', array_keys($value)));
}
Expand All @@ -89,6 +104,9 @@ public function toArray(): array
if (isset($this->_usedProperties['errorPages'])) {
$output['error_pages'] = $this->errorPages instanceof \Symfony\Config\ArrayValues\ErrorPagesConfig ? $this->errorPages->toArray() : $this->errorPages;
}
if (isset($this->_usedProperties['places'])) {
$output['places'] = array_map(fn ($v) => $v->toArray(), $this->places);
}

return $output;
}
Expand Down
Loading