Follow up for #2863778-19: Clean up \Drupal\hal\Normalizer\NormalizerBase: duplicate less from the parent class \Drupal\serialization\Normalizer\NormalizerBase:

@BR0kEN - it's the lack of the third argument and it not being TRUE that scares me. Pretty much people always want in_array($needle, $haystack, TRUE) and not in_array($needle, $haystack) - see https://3v4l.org/sr29Y

Problem/Motivation

Normalizer could define type(s) of data which they wants to normalize using supportedInterfaceOrClass property of \Drupal\serialization\Normalizer\NormalizerBase. The same available for request types, which are accepted by normalizer (using format property).

In both cases these properties will be casted to an array to be handled by in_array() function to find the matches and, in both cases, this will happen without strict data comparison which could cause potential inconsistences.

Proposed resolution

  1. Add TRUE as third argument to every in_array() function in \Drupal\serialization\Normalizer\NormalizerBase
  2. Add tests

Issue fork drupal-2864495

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

BR0kEN created an issue. See original summary.

wim leers’s picture

Category: Feature request » Task
Priority: Normal » Minor
Issue tags: -serialization
wim leers’s picture

Issue summary: View changes
damiankloip’s picture

I think we could just add the third parameter to the in_array() call in supportsDenormalization(), not sure what other tests we need there? I guess we can just add a couple of tests to \Drupal\Tests\serialization\Unit\Normalizer\NormalizerBaseTest::testSupportsNormalization.

The !isset() vs empty() for the $format check, I'm not sure of the benefits. If it's something empty like '' or 0 it's unlikely that the format property will match that. Seems like too much baby sitting, potentially?

wim leers’s picture

Issue summary: View changes
Issue tags: +php-novice, +Novice

#4 sounds sensible. Removed point 2 from the IS per #4.

Everything except the tests should be doable by a novice, so adding tags.

damiankloip’s picture

+++ Thanks, Wim!

dinesh18’s picture

Status: Active » Needs review
StatusFileSize
new701 bytes

Here is the patch which adds third argument TRUE to in_array functions.

wim leers’s picture

Issue summary: View changes
Status: Needs review » Needs work
Issue tags: -php-novice, -Novice

Thanks! Now task 1 is done. Updated issue summary.

Now task 2 remains.

dinesh18’s picture

Thanks Wim for reviewing the patch.
Could you please help me how to create Tests as I am creating it for the first time.

damiankloip’s picture

Please see comment #4, I think the test I mentioned there can be added to, to cover this edge case.

dinesh18’s picture

Thanks damiankloip. I will work on the Tests as mentioned in #4

dinesh18’s picture

Test case : \Drupal\Tests\serialization\Unit\Normalizer\NormalizerBaseTest::testSupportsNormalization
if (!isset($format) && empty($format)) {
$this->assertNull($format, 'Null Value');
}

Could you please manually review if it looks good so that I can create the patch.

wim leers’s picture

\Drupal\Tests\serialization\Unit\Normalizer\NormalizerBaseTest::testSupportsNormalization() is testing supportsNormalization(). The change made in #7 modifies supportsDenormalization().

So it's not quite correct yet, but you're thinking along the right lines.

The point here is: add a test that fails if #7 is not applied, and hence demonstrates the bug. Then apply #7, and the test should pass.

damiankloip’s picture

Right. You will want to add a new test method (and data provider maybe) for supportsDenormalization I think.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

wim leers’s picture

Pinged @Dinesh18.

dinesh18’s picture

I have tried creating one default function testSupportsDenormalization() mentioned below. It is hard-coded which always returns TRUE.
Could you please help me how can I pass values to function supportsDenormalization($data, $type, $format = NULL).

class NormalizerBaseTest extends UnitTestCase {

  /**
   * Tests the supportsDenormalization method.
   *
 public function testSupportsDenormalization() {
    $data = array('1.10', 12.4, 1.13);
    $output = in_array(1.13, $data, true);
    $this->assertSame($output, TRUE);
  }

}
wim leers’s picture

Issue tags: +API-First Initiative, +Novice, +php-novice

@Dinesh18: you want to create a "data provider" function. See \Drupal\Tests\serialization\Unit\Normalizer\NormalizerBaseTest::testSupportsNormalization()'s docblock + \Drupal\Tests\serialization\Unit\Normalizer\NormalizerBaseTest::providerTestSupportsNormalization() for an example.

ivan berezhnov’s picture

Issue tags: +CSKyiv18

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

jamesdixon’s picture

Assigned: Unassigned » jamesdixon

I'll take a crack at writing this test at the PNWDS.

jamesdixon’s picture

Here's my attempt at testSupportsDenormalization. This test should have 3 failures with the current patch because I did not include the solution in#7.

jamesdixon’s picture

This new patch includes the fix in #7 and should pass all tests.

jamesdixon’s picture

Assigned: jamesdixon » Unassigned
Status: Needs work » Needs review
borisson_’s picture

Status: Needs review » Needs work
  1. +++ b/core/modules/serialization/tests/src/Unit/Normalizer/NormalizerBaseTest.php
    @@ -61,6 +61,50 @@ public function providerTestSupportsNormalization() {
    +    $normalizer_base = $this->getMockForAbstractClass('Drupal\Tests\serialization\Unit\Normalizer\TestNormalizerBase');
    

    This should be TestNormalizerBase::class, to make refactoring easier.

  2. +++ b/core/modules/serialization/tests/src/Unit/Normalizer/NormalizerBaseTest.php
    @@ -61,6 +61,50 @@ public function providerTestSupportsNormalization() {
    +  public function providerTestSupportsDenormalization() {
    

    This data provider should also test positive return values, not just negative return values.

    So at least one of them shuold be

    [TRUE, new \stdClass, '123', $supported_types],
    
savkaviktor16@gmail.com’s picture

Status: Needs work » Needs review
StatusFileSize
new3 KB
new1.72 KB
borisson_’s picture

Status: Needs review » Reviewed & tested by the community

Awesome, thanks for fixing those @Saviktor. This looks done.

br0ken’s picture

Status: Reviewed & tested by the community » Needs work
  1. +++ b/core/modules/serialization/tests/src/Unit/Normalizer/NormalizerBaseTest.php
    @@ -61,6 +61,56 @@ public function providerTestSupportsNormalization() {
    +   * @dataProvider providerTestSupportsDenormalization
    

    PHPCS: Parameter tags must be defined first in a doc comment.

  2. +++ b/core/modules/serialization/tests/src/Unit/Normalizer/NormalizerBaseTest.php
    @@ -61,6 +61,56 @@ public function providerTestSupportsNormalization() {
    +  public function testSupportsDenormalization($expected_return, $data, $supported_interface_or_class = NULL, $supported_types) {
    

    The #4 argument must have a default value defined.

  3. +++ b/core/modules/serialization/tests/src/Unit/Normalizer/NormalizerBaseTest.php
    @@ -61,6 +61,56 @@ public function providerTestSupportsNormalization() {
    +    $supported_types = array(
    

    Avoid mixing the array() and [].

savkaviktor16@gmail.com’s picture

savkaviktor16@gmail.com’s picture

Status: Needs work » Needs review
br0ken’s picture

Status: Needs review » Needs work
+++ b/core/modules/serialization/tests/src/Unit/Normalizer/NormalizerBaseTest.php
@@ -64,19 +64,21 @@ public function providerTestSupportsNormalization() {
+  public function testSupportsDenormalization($expected_return, $data, $supported_interface_or_class = NULL, array $supported_types = []) {

Let's have null as the default value since it means "really nothing" in comparison to an empty array, which is an empty value. Therefore isset() can be returned back.

mohit1604’s picture

Assigned: Unassigned » mohit1604
mohit1604’s picture

Assigned: mohit1604 » Unassigned
Status: Needs work » Needs review
StatusFileSize
new815 bytes
new3.12 KB

Did changes as per comment #31, please review it :)

andypost’s picture

+++ b/core/modules/serialization/tests/src/Unit/Normalizer/NormalizerBaseTest.php
@@ -75,7 +75,7 @@
+  public function testSupportsDenormalization($expected_return, $data, $supported_interface_or_class = NULL, $supported_types = NULL) {
...
     if (!empty($supported_types)) {

then makes sense to change condition to isset()

br0ken’s picture

Status: Needs review » Needs work

Agree with the above.

wim leers’s picture

  1. +++ b/core/modules/serialization/tests/src/Unit/Normalizer/NormalizerBaseTest.php
    @@ -61,6 +61,58 @@ public function providerTestSupportsNormalization() {
    +   * @param mixed $data
    +   *   The data passed to supportsNormalization.
    ...
    +      [FALSE, new \stdClass(), '1.10', $supported_types],
    

    This is always new \stdClass, so there's no need to pass it in.

  2. +++ b/core/modules/serialization/tests/src/Unit/Normalizer/NormalizerBaseTest.php
    @@ -61,6 +61,58 @@ public function providerTestSupportsNormalization() {
    +      // If string '1.10' type is passed should return FALSE.
    

    These comments should be the keys to the test cases: that's how you label test cases. Then if a test case fails, you get that label instead of a number!

br0ken’s picture

StatusFileSize
new3.23 KB
new2.71 KB
br0ken’s picture

  1. +++ b/core/modules/serialization/tests/src/Unit/Normalizer/NormalizerBaseTest.php
    @@ -66,50 +66,48 @@
        * @param bool $expected_return
    

    The other problem I see is that the supportsDenormalization() might return an array instead of boolean.

  2. +++ b/core/modules/serialization/tests/src/Unit/Normalizer/NormalizerBaseTest.php
    @@ -66,50 +66,48 @@
    +   * @param string|int|float $type
    +   *   An interface, class or value to check for denormalization support.
    +   * @param string|string[] $format
    +   *   (optional) An interface, class or value the denormalization is supported
    +   *   for.
    

    I've taken method's params and their types from the original class.

  3. +++ b/core/modules/serialization/tests/src/Unit/Normalizer/NormalizerBaseTest.php
    @@ -66,50 +66,48 @@
    +      // @todo This should fail since the class is missing.
    +      'Ns\Of\MissingClass',
    

    This should be prevented somehow IMO.

br0ken’s picture

Status: Needs work » Needs review
Issue tags: -CSKyiv18
StatusFileSize
new3.46 KB
new2.11 KB

In my imagination, it should be something like that. Please review.

br0ken’s picture

StatusFileSize
new2.86 KB
new4.8 KB

Extended tests coverage plus added documentation.

wim leers’s picture

Status: Needs review » Needs work

This patch is now changing much more.

  1. +++ b/core/modules/serialization/src/Normalizer/NormalizerBase.php
    @@ -42,11 +42,23 @@ public function supportsNormalization($data, $format = NULL) {
    +   * @param string|object $type
    
    @@ -56,11 +68,21 @@ public function supportsDenormalization($data, $type, $format = NULL) {
    +    if (
    +      // Object types should be checked.
    +      is_object($type) ||
    

    When can this ever be an object? That is not actually allowed by \Symfony\Component\Serializer\Normalizer\DenormalizerInterface::supportsDenormalization().

  2. +++ b/core/modules/serialization/tests/src/Unit/Normalizer/NormalizerBaseTest.php
    @@ -61,6 +61,64 @@ public function providerTestSupportsNormalization() {
    +   * @param string|int|float $type
    

    This is not actually allowed to contain an int or a float. Again, see \Symfony\Component\Serializer\Normalizer\DenormalizerInterface::supportsDenormalization().

br0ken’s picture

Then why do we need in_array() with TRUE?

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

rosk0’s picture

Issue tags: -

I would really love to see something like META Use strict mode for "in_array()" calls as parent of this to fix this big bug possibility once and for all the core.

RE #42 - read issue description and check the link there.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

andypost’s picture

yevko’s picture

ayush.khare made their first commit to this issue’s fork.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.