Skip to content
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

[Serializer] add a context key to return always as collection for XmlEncoder #25369

Conversation

Simperfit
Copy link
Contributor

@Simperfit Simperfit commented Dec 7, 2017

Q A
Branch? 4.1
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #25227
License MIT
Doc PR

This PR add a new as_collection context key in order to return always as a collection instead of returning a single elements when there are only one array.

there are only one PR for the CsvEncoder don't wanted to have only One PR containing the two changes. It feel better to have two PR that fix the behaviour on two different things. it's easy to review and to revert if it break something (which should not since we are testing the behaviour).

@Simperfit
Copy link
Contributor Author

Travis failure is unrelated.

@nicolas-grekas nicolas-grekas added this to the 4.1 milestone Dec 8, 2017

/**
* Construct new XmlEncoder and allow to change the root node element name.
*
* @param string $rootNodeName
* @param int|null $loadOptions A bit field of LIBXML_* constants
*/
public function __construct(string $rootNodeName = 'response', int $loadOptions = null)
public function __construct(string $rootNodeName = 'response', int $loadOptions = null/*, bool $alwaysCollection = false */)
Copy link
Member

Choose a reason for hiding this comment

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

args can be appended to constructors, no need for the "BC layer"

@@ -257,7 +262,6 @@ private function parseXml(\DOMNode $node, array $context = array())

if (1 === count($value) && key($value)) {
$data[key($value)] = current($value);

Copy link
Member

Choose a reason for hiding this comment

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

?

@@ -515,6 +515,39 @@ public function testDecodeIgnoreWhiteSpace()
$this->assertEquals($expected, $this->encoder->decode($source, 'xml'));
}

/**
* @group collection
Copy link
Member

Choose a reason for hiding this comment

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

why adding this?

$source = <<<'XML'
<?xml version="1.0"?>
<order_rows nodeType="order_row" virtualEntity="true">
<order_row>
Copy link
Member

Choose a reason for hiding this comment

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

indentation is strange, is it normal?

);

$this->assertEquals($expected, $this->encoder->decode($source, 'xml'));
}
Copy link
Member

Choose a reason for hiding this comment

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

missing blank line after

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added

@Simperfit Simperfit force-pushed the feature/add-a-constructor-arguement-to-return-xml-alsways-as-collection branch 2 times, most recently from 8dab446 to 658fb0e Compare December 9, 2017 08:00
@Simperfit
Copy link
Contributor Author

AppVeyor failure is not related.

@Simperfit
Copy link
Contributor Author

Status: Needs Review

@Simperfit Simperfit force-pushed the feature/add-a-constructor-arguement-to-return-xml-alsways-as-collection branch from 658fb0e to a582455 Compare December 14, 2017 07:11
*/
public function __construct(string $rootNodeName = 'response', int $loadOptions = null)
public function __construct(string $rootNodeName = 'response', int $loadOptions = null, bool $alwaysCollection = false)
Copy link
Member

Choose a reason for hiding this comment

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

$forceCollection?

@Simperfit Simperfit force-pushed the feature/add-a-constructor-arguement-to-return-xml-alsways-as-collection branch from a582455 to 6f749bc Compare January 5, 2018 12:07
@dunglas
Copy link
Member

dunglas commented Jan 11, 2018

@Simperfit can you rebase to force the CI to run again?

@Simperfit Simperfit force-pushed the feature/add-a-constructor-arguement-to-return-xml-alsways-as-collection branch from 6f749bc to 7a3d918 Compare January 11, 2018 11:14
@Simperfit
Copy link
Contributor Author

done @dunglas

@Simperfit
Copy link
Contributor Author

This is ready to be merged.

@@ -335,7 +336,7 @@ private function parseXmlValue(\DOMNode $node, array $context = array())
}

foreach ($value as $key => $val) {
if (is_array($val) && 1 === count($val)) {
if (is_array($val) && 1 === count($val) && (!$this->forceCollection || !is_array($val[0]))) {
Copy link
Member

Choose a reason for hiding this comment

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

After a second thought, wouldn't it be better to allow to change this behavior through the context instead of forcing to register a new instance of the class?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think it will be easier to use if we don't create a new instance. Ill do the modification on both PRs

@Simperfit Simperfit force-pushed the feature/add-a-constructor-arguement-to-return-xml-alsways-as-collection branch 2 times, most recently from 89a4381 to f1daa3f Compare February 2, 2018 11:08
@Simperfit
Copy link
Contributor Author

@dunglas it now use a context key.

foreach ($value as $key => $val) {
if (is_array($val) && 1 === count($val)) {
if (is_array($val) && 1 === count($val) && (!(isset($context['forceCollection']) && $context['forceCollection']) || !is_array($val[0]))) {
Copy link
Member

Choose a reason for hiding this comment

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

should use snake_case also I suppose

@@ -333,9 +332,8 @@ private function parseXmlValue(\DOMNode $node, array $context = array())
$value[$subnode->nodeName][] = $val;
}
}

Copy link
Member

Choose a reason for hiding this comment

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

let's keep this line :)

@Simperfit Simperfit force-pushed the feature/add-a-constructor-arguement-to-return-xml-alsways-as-collection branch 2 times, most recently from 8f3a88d to b0daf42 Compare February 5, 2018 09:08
@Simperfit
Copy link
Contributor Author

done @nicolas-grekas

@Simperfit Simperfit force-pushed the feature/add-a-constructor-arguement-to-return-xml-alsways-as-collection branch from b0daf42 to 7c8709e Compare February 5, 2018 09:10
@@ -41,8 +41,7 @@ class XmlEncoder implements EncoderInterface, DecoderInterface, NormalizationAwa
/**
* Construct new XmlEncoder and allow to change the root node element name.
*
* @param string $rootNodeName
* @param int|null $loadOptions A bit field of LIBXML_* constants
* @param int|null $loadOptions A bit field of LIBXML_* constants
Copy link
Member

Choose a reason for hiding this comment

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

let's revert this: it's unrelated, and breaks merges

@@ -335,7 +334,7 @@ private function parseXmlValue(\DOMNode $node, array $context = array())
}

foreach ($value as $key => $val) {
if (is_array($val) && 1 === count($val)) {
if (is_array($val) && 1 === count($val) && (!(isset($context['as_collection']) && $context['as_collection']) || !is_array($val[0]))) {
Copy link
Member

Choose a reason for hiding this comment

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

using empty() would make the code simpler I suppose
I don't understand the last condition !is_array($val[0]) - it feels unrelated. Is it?

Copy link
Contributor Author

@Simperfit Simperfit Feb 16, 2018

Choose a reason for hiding this comment

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

I just looked after it and !is_array($val[0]) makes it possible to return the value directly instead of having two arrays:

$expected = array(
            '@nodeType' => 'order_row',
            '@virtualEntity' => 'true',
            'order_row' => array(array(
                'id' => 16,
                'test' => 16,
            )),
        );

vs

$expected = array(
            '@nodeType' => 'order_row',
            '@virtualEntity' => 'true',
            'order_row' => array(array(
                'id' => array(16),
                'test' => array(16),
            )),
        );

Do you mean replacing

is_array($val) && 1 === count($val)

to

!empty($val)

it's not possible

@Simperfit Simperfit force-pushed the feature/add-a-constructor-arguement-to-return-xml-alsways-as-collection branch from 7c8709e to 5319a86 Compare February 16, 2018 08:54
@Simperfit Simperfit force-pushed the feature/add-a-constructor-arguement-to-return-xml-alsways-as-collection branch from 5319a86 to adb428d Compare February 16, 2018 09:06
Copy link
Member

@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

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

Please update the main description so that people looking at this PR can understand what's going on here.
Please also check if a doc PR should be done.

@Simperfit Simperfit changed the title [Serializer] add a contruct key to return always as collection for XmlEncoder [Serializer] add a context key to return always as collection for XmlEncoder Feb 19, 2018
@Simperfit
Copy link
Contributor Author

@nicolas-grekas done.

@dunglas
Copy link
Member

dunglas commented Feb 19, 2018

Thank you @Simperfit.

@dunglas dunglas merged commit adb428d into symfony:master Feb 19, 2018
dunglas added a commit that referenced this pull request Feb 19, 2018
…lection for XmlEncoder (Simperfit)

This PR was merged into the 4.1-dev branch.

Discussion
----------

[Serializer] add a context key to return always as collection for XmlEncoder

| Q             | A
| ------------- | ---
| Branch?       | 4.1
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no <!-- don't forget to update UPGRADE-*.md files -->
| Tests pass?   | yes
| Fixed tickets | #25227
| License       | MIT
| Doc PR        |

This PR add a new `as_collection` context key in order to return always as a collection instead of returning a single elements when there are only one array.

there are only one PR for the CsvEncoder don't wanted to have only One PR containing the two changes. It feel better to have two PR that fix the behaviour on two different things. it's easy to review and to revert if it break something (which should not since we are testing the behaviour).

Commits
-------

adb428d [Serializer] add a context key to return always as collection for XmlEncoder
@fabpot fabpot mentioned this pull request May 7, 2018
fabpot added a commit that referenced this pull request Jun 30, 2018
…default value (ogizanagi)

This PR was merged into the 4.2-dev branch.

Discussion
----------

[Serializer] Deprecate CsvEncoder as_collection false default value

| Q             | A
| ------------- | ---
| Branch?       | master <!-- see below -->
| Bug fix?      | no
| New feature?  | no <!-- don't forget to update src/**/CHANGELOG.md files -->
| BC breaks?    | no     <!-- see https://symfony.com/bc -->
| Deprecations? | yes <!-- don't forget to update UPGRADE-*.md and src/**/CHANGELOG.md files -->
| Tests pass?   | yes    <!-- please add some, will be required by reviewers -->
| Fixed tickets | N/A   <!-- #-prefixed issue number(s), if any -->
| License       | MIT
| Doc PR        | N/A

As already expressed in #25369 and related issues, this behavior is quite counter-intuitive. It may be fine for write-API with a single document in the body but I think such CSV APIs are way less common than file-based ones, expecting collections. So I think this behavior should be opt-in explicitly in required cases, always dealing with collections by default.
This is still an arbitrary decision, but trying to make it based on use-cases and user's experience with CSV.

Note: perhaps we could find a better name for this as the semantic of setting `as_collection` to `false` to get the single row directly would not be really obvious.
Also, it could throw an exception when getting multiple rows where only one was expected.

Commits
-------

bce59c8 [Serializer] Deprecate CsvEncoder as_collection false default value
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants