Problem/Motivation

BlockFieldItem currently doesn't provide a custom field normalizer. Having no custom field normalizer can cause issues when we want to normalize the block field item values. One use case would be, exporting default content for example.

The issue because a problem when using a "settings" field property (MapDataDefinition) which doesn't support normalization at all.

Proposed resolution

Create a custom block field item normalizer and expose it in case there is a hal module available.

Remaining tasks

User interface changes

API changes

Data model changes

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

mbovan created an issue. See original summary.

mbovan’s picture

Status: Active » Needs review
FileSize
2.31 KB

Adding a patch that provides normalization for the settings field property as well.

Wim Leers’s picture

Status: Needs review » Needs work
Issue tags: +API-First Initiative, +Needs tests
  1. Why does this need a HAL normalizer but not a "default" normalizer (i.e. for json, xml, etc)?
  2. +++ b/src/BlockFieldServiceProvider.php
    @@ -0,0 +1,32 @@
    +      $service_definition->addTag('normalizer', ['priority' => 20]);
    

    Documenting the reason for this priority is useful for future maintainability.

    At least until #2575761: Discuss a better system for discovering and selecting normalizers is fixed.

  3. +++ b/src/Normalizer/BlockFieldItemNormalizer.php
    @@ -0,0 +1,33 @@
    +   * The interface or class that this Normalizer supports.
    +   *
    +   * @var string
    

    {@inheritdoc}

  4. +++ b/src/Normalizer/BlockFieldItemNormalizer.php
    @@ -0,0 +1,33 @@
    +    // Let HAL normalizer do the initial normalization.
    

    s/HAL normalizer/HAL field item normalizer/

  5. +++ b/src/Normalizer/BlockFieldItemNormalizer.php
    @@ -0,0 +1,33 @@
    +    // Normalize settings property.
    +    $data[$field_item->getParent()->getName()][0]['settings'] = $field_item->settings;
    

    Hrm, what is this actually normalizing?

    If there were tests, this would actually be clear.

Wim Leers’s picture

Title: Add custom hal normalizer » Add custom HAL normalizer

For an example for tests, see \Drupal\Tests\serialization\Unit\Normalizer\TimestampItemNormalizerTest + ideally also integration tests (for which I can also find you an example), but having at least such a unit test would be very valuable.

(Because TimestampItemNormalizer extends FieldItemNormalizer, just like this.)

John Cook’s picture

I've moved the service provider definition into services.yml instead of a custom class.

Changed the comments as suggested by Wim in #3.

@Wim; creating at test is causing be a bit of trouble. If I mock BlockFieldItem, as with TimestampItemNormalizerTest, then the normalizer can't get the settings property. I've also tried to instantiate BlockFieldItem mocking other things but I'm having trouble getting it to work; if you know of anywhere I can see an example that would be helpful.

Further detail about mocking
Using $field_item->settings:

  • BlockFieldItem returns an array as expected using it's magic getter.
  • The mock returns NULL, probably because the property doesn't exist on the mock.

Using a foreach ($field_item as $property_name => $property) loop:

  • BlockFieldItem returns a \Drupal\Core\TypedData\Plugin\DataType\Map object.
  • The mock return the array as expected.

I could put in a check, but wouldn't the mean that the code would not be checked correctly?

Status: Needs review » Needs work

The last submitted patch, 5: add_custom_hal_normalizer-2882727-5.patch, failed testing. View results

Berdir’s picture

The service provider is required because this module also needs to work without the hal module

John Cook’s picture

Thanks Berdir. I've reverted to use the custom service provider. There's interdiffs of this patch with the patches int #2 and #5.

Status: Needs review » Needs work

The last submitted patch, 8: add_custom_hal_normalizer-2882727-8.patch, failed testing. View results

John Cook’s picture

Now I've got no idea what testbot wants.

It works locally.

vagrant@drupal8 ✝ /var/www/site/docroot (8.3.x)
$ php ./core/scripts/run-tests.sh block_field

Drupal test run
---------------

Tests to be run:
  - Drupal\block_field\Tests\BlockFieldTest
  - Drupal\Tests\block_field\Functional\WidgetTest

Test run started:
  Tuesday, August 1, 2017 - 15:08

Test summary
------------

Drupal\block_field\Tests\BlockFieldTest                       72 passes                                      
Drupal\Tests\block_field\Functional\WidgetTest                 1 passes                                      

Test run duration: 1 min 15 sec
Berdir’s picture

Tests are run against 8.4, you are likely on 8.3.

Try removing the administer nodes permission then the UI is the same on 8.4 and 8.3. But that should be a separate issue, that's an existing fail.

JamesK’s picture

Why does it depend on hal rather than serialization? You should be able to extend Drupal\serialization\Normalizer\FieldItemNormalizer to use this more generically.

Also, this is likely to require follow-up after #2895532: @DataType=map cannot be normalized, affects @FieldType=link, @FieldType=map

JamesK’s picture

Status: Needs work » Postponed

As the patch is now in #2895532: @DataType=map cannot be normalized, affects @FieldType=link, @FieldType=map (#96) it actually fixes this issue without anything needing to happen here.

Berdir’s picture

Status: Postponed » Closed (duplicate)

Agreed, closing as a duplicate of the core issue.