Part of meta-issue #2016679: Expand Entity Type interfaces to provide methods, protect the properties.

See the detailed explanations there and look at the issues that already have patches or were committed.

Add get*, set* and additional methods as it makes sense to replace the public properties (e.g. isSomething() and something())

For beta evaluation, see the meta.

Proposed resolution

New methods added to the FieldConfigInterface. setTranslatable() was also added to FieldConfigInterface even though it was not introduced in this patch.

Here is a table with class properties and associated methods and notes about each to help reviewers. The elements in bold are the ones that have been added in this series of patches. The notes try to compile most of the previous comments into why we have or haven't added certain getters and setters.

Property Visibility (before) Visibility (after) Get Method Set Method Notes
$id public protected (todo) id() N/A The getter will eventually need to be changed to getId() per #2246695: replace all core usages of id() with getid().
There is no setter for $id because it is derived from $field_name and $entity_type
$field_name public protected (todo) getName() N/A There is no setter for $name because it is set in the constructor. See #26.
$entity_type public protected (todo) getTargetEntityTypeId() N/A There is no setter because it is set in the constructor. See #50.
$type public protected (todo) getType() N/A There is no setter for $name because it is set in the constructor. See #26.
$module public protected (todo) getTypeProvider() (see #154) N/A $module is derived from the field type. See #26.
$settings public protected (todo) getSetings()
getSetting()
setSettings()
setSetting()
setSettings will overwrite the entire $settings property. setSetting will set a key within the settings array. This functionality mimics the existing getSettings and getSetting methods.
$cardinality public protected (todo) getCardinality() setCardinality()
$translatable public protected (todo) isTranslatable() setTranslatable() Not added in this patch. setTranslatable was added to FieldConfigInterface.
$locked public protected (todo) isLocked() setLocked()
$indexes public protected (todo) N/A N/A There is no setter because it is set as part of the schema. See #50.
$deleted public
protected (done in #93)
isDeleted() N/A
$schema protected no change getSchema() N/A Not added in this patch.

Remaining tasks

Contributor tasks needed
Task Novice task? Contributor instructions Complete?
Create a patch making one of the properties protected (include an interdiff) Novice Instructions done in #93
Create a patch replacing direct usages of the properties with calls to methods (test results from making the properties is useful) (include an interdiff) Not novice Instructions
Review patch to ensure that it fixes the issue, stays within scope, is properly documented, and follows coding standards Instructions

For reviewers:

CommentFileSizeAuthor
#209 interdiff.txt1.27 KBMile23
#209 2030633_209.patch85.18 KBMile23
#203 interdiff.txt12.28 KBMile23
#203 2030633_203.patch85.5 KBMile23
#192 interdiff.txt724 bytesMile23
#192 2030633_192.patch85.83 KBMile23
#192 2030633_192.patch85.83 KBMile23
#190 2030633_190.patch85.12 KBMile23
#181 interdiff.txt4.49 KBMile23
#181 2030633_181.patch83.32 KBMile23
#177 2030633-177.patch82.64 KBMile23
#171 2030633-171.patch82.39 KBhussainweb
#171 interdiff-170-171.txt1.3 KBhussainweb
#170 2030633-170.patch82.72 KBhussainweb
#170 interdiff-168-170.txt6.86 KBhussainweb
#168 2030633-168.patch82.13 KBhussainweb
#168 interdiff-166-168.txt8.46 KBhussainweb
#166 2030633-166.patch82.71 KBhussainweb
#166 interdiff-164-166.txt6.73 KBhussainweb
#164 2030633-164.patch82.65 KBhussainweb
#164 interdiff-162-164.txt1.57 KBhussainweb
#162 2030633-162.patch81.08 KBhussainweb
#160 2030633-160.patch81.44 KBhussainweb
#158 2030633-158.patch81.44 KBhussainweb
#145 2030633-145.patch85.14 KBhussainweb
#145 interdiff-141-145.txt601 byteshussainweb
#141 2030633-141.patch85.04 KBhussainweb
#141 interdiff-140-141.txt5.43 KBhussainweb
#140 2030633-140.patch81.48 KBhussainweb
#140 interdiff-136-140.txt2.23 KBhussainweb
#136 2030633-136.patch81.47 KBhussainweb
#136 interdiff-135-136.txt4.49 KBhussainweb
#135 2030633-135.patch77.63 KBhussainweb
#135 interdiff-133-135.txt552 byteshussainweb
#133 2030633-133.patch77.37 KBhussainweb
#133 interdiff-132-133.txt14.58 KBhussainweb
#132 2030633-132.patch68.15 KBhussainweb
#132 interdiff-130-132.txt950 byteshussainweb
#130 2030633-130.patch67.94 KBhussainweb
#130 interdiff-128-130.txt1.28 KBhussainweb
#128 2030633-128.patch67.46 KBhussainweb
#128 interdiff-126-128.txt4.14 KBhussainweb
#126 2030633-126.patch63.8 KBhussainweb
#126 interdiff-124-126.txt4.15 KBhussainweb
#124 2030633-124.patch61.08 KBhussainweb
#124 interdiff-122-124.txt646 byteshussainweb
#122 2030633-122.patch61.03 KBhussainweb
#122 interdiff-119-122.txt12.67 KBhussainweb
#119 2030633_119-interdiff.txt2.9 KBBerdir
#119 2030633_119.patch49.17 KBBerdir
#115 interdiff_114.txt1.54 KBMile23
#115 2030633_115.patch46.28 KBMile23
#114 2030633_114.patch45.26 KBMile23
#114 interdiff_112.txt1.69 KBMile23
#112 interdiff_108.txt2.64 KBMile23
#112 2030633_112.patch43.57 KBMile23
#110 interdiff_105.txt14.36 KBMile23
#110 2030633_108.patch40.92 KBMile23
#105 interdiff_80.patch13.94 KBMile23
#105 2030633_104.patch26.84 KBMile23
#93 interdiff.txt491 bytesfernando_calsa
#93 2030633-92.patch9.86 KBfernando_calsa
#80 interdiff.txt936 bytesMile23
#80 2030633_80.patch9.64 KBMile23
#77 2030633_77.patch10.1 KBMile23
#69 2030633-expand-fieldconfig-and-interface-with-methods-69.patch10.2 KBJānis Bebrītis
#64 2030633-expand-fieldconfig-and-interface-with-methods-64.patch10.71 KBundertext
#60 2030633-expand-fieldconfig-and-interface-with-methods-60.patch11.26 KBamitgoyal
#53 interdiff-51-53.txt574 bytescarsonevans
#53 interdiff-46-53.txt6.13 KBcarsonevans
#53 2030633-expand-fieldconfig-and-interface-with-methods-53.patch11.6 KBcarsonevans
#51 2030633-expand-fieldconfig-and-interface-with-methods-51.patch11.8 KBcarsonevans
#51 interdiff-46-51.txt5.8 KBcarsonevans
#46 2030633-expand-fieldconfig-with-methods-46.patch10.63 KBcarsonevans
#43 2030633-expand-fieldconfig-with-methods-43.patch10.63 KBcarsonevans
#39 interdiff-38-39.txt2.54 KBcarsonevans
#39 2030633-DO_NOT_COMMIT_making_properties_protected_to_see_what_other_code_is_referenceing_them-39.patch12.93 KBcarsonevans
#38 2030633-expand-fieldconfig-with-methods-38.patch10.63 KBGeijutsuka
#38 interdiff-2030633-33-38.txt650 bytesGeijutsuka
#34 2030633-add_setters_to_fieldconfig-33.patch10.59 KBcarsonevans
#34 interdiff-33.txt732 bytescarsonevans
#32 interdiff-32.txt1.3 KBcarsonevans
#32 2030633-rerolled_with_ycheds_comments_applied-32.patch10.63 KBcarsonevans
#30 2030633-rebase_of_12-30.patch11.38 KBcarsonevans
#27 interdiff.txt1.53 KBcarsonevans
#27 2030633-add_setters_to_fieldconfig-27.patch2.28 KBcarsonevans
#24 2030633-add_setters_to_fieldconfig-24.patch3.51 KBcarsonevans
#14 core-expand_field_config-2030633-14.patch116.75 KBczigor
#14 interdiff-12-14.txt95.94 KBczigor
#12 interdiff-9-12.txt651 bytesczigor
#12 core-expand_field_config-2030633-12.patch11.65 KBczigor
#9 core-expand_field_config-2030633-9.patch11.63 KBczigor
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

japicoder’s picture

Assigned: Unassigned » japicoder

Start to work on this ...

YesCT’s picture

@japicoder Did you have any questions or intermediate work to post?

swentel’s picture

Status: Active » Postponed
swentel’s picture

Alumei’s picture

Issue summary: View changes
Status: Postponed » Active

That issue seems to be resolved. Back to active.

Alumei’s picture

List of public property's found via the FieldConfig API documentation:

  • FieldConfig::$id
  • FieldConfig::$name
  • FieldConfig::$entity_type
  • FieldConfig::$type
  • FieldConfig::$module
  • FieldConfig::$settings
  • FieldConfig::$cardinality
  • FieldConfig::$translatable
  • FieldConfig::$locked
  • FieldConfig::$indexes
  • FieldConfig::$deleted
Alumei’s picture

Title: Expand Field with methods » Expand FieldConfig with methods

Renamed to match the new classname.

czigor’s picture

Assigned: japicoder » czigor
czigor’s picture

This is the first draft, changing only things in FieldConfig.php. As a consequence, properties are still public to see if the tests fail already. (See #14.)

Getters-setters table
('+' means added in the patch, '-' means none):

property; getter; setter
id; id(); -
name; getName(); +setName()
entity_type; getTargetEntityTypeId(); +setTargetEntityTypeId()
type; getType(); +setType()
module; +getModule(); +setModule()
settings; getSettings(); +setSettings() (also added a setSetting() method)
cardinality; getCardinality(); +setCardinality()
translatable; isTranslatable(); setTranslatable()
locked; isLocked(); +setLocked()
indexes; +getIndexes(); +setIndexes()
deleted; +isDeleted(); +setDeleted()

Not sure about

  1. when to use the set() method in setters and when to just assign the value. I have found examples for both. For the former see CustomBlock::setInfo(). For the latter see FieldConfig::setTranslatable().
  2. if getters and setters should be declared in the interface or not. If so, in which one: FieldConfigInterface or FieldDefinitionInterface?
  3. who needs setters and who don't.
  4. whether leaving $this->setters occurences this way is ok.
czigor’s picture

Status: Active » Needs review

Status: Needs review » Needs work

The last submitted patch, 9: core-expand_field_config-2030633-9.patch, failed testing.

czigor’s picture

Status: Needs work » Needs review
FileSize
11.65 KB
651 bytes
czigor’s picture

Status: Needs review » Needs work

Patch passed tests, so let's replace other occurences of direct property access to getters and setters.

czigor’s picture

Assigned: czigor » Unassigned
Status: Needs work » Needs review
FileSize
95.94 KB
116.75 KB

I found contradictory informations on whether the properties should be public or protected. The following patch sets all properties to protected. Also replaced all direct access to FieldConfig properties with getters and setters (ie. all that I found).

czigor’s picture

Status: Needs review » Needs work

The last submitted patch, 14: core-expand_field_config-2030633-14.patch, failed testing.

swentel’s picture

Note - berdir told not to make them protected so the patch in #12 is good.

czigor’s picture

Status: Needs work » Needs review

So the patch in #12 needs review.

msonnabaum’s picture

Status: Needs review » Needs work

I'm sorry, but keeping the properties public completely defeats the purpose of this. The test failures on the protected version are showing very clearly that the job simply isn't finished.

Please make them protected and continue converting usages to use the new methods.

mashermike’s picture

Issue tags: +Needs reroll

Needs a reroll of the patch from #14.

sundersingh’s picture

Assigned: Unassigned » sundersingh

Will be working on this task; assigned via core mentoring.

sundersingh’s picture

Assigned: sundersingh » Unassigned
carsonevans’s picture

Assigned: Unassigned » carsonevans

I'm gonna attempt to tackle this.

carsonevans’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll
FileSize
3.51 KB

My first patch. Hopefully it's not too ugly!

carsonevans’s picture

I should have included this info in comment 24 but forgot to. Here is a summary of my tasks with a few notes about things I did not do and why...

Changes:
- added setName to set $name
- added setType to set $type
- added setModule and getModule to set/get $module
- added setCardinality to set $cardinality
- added lock() and unlock() to handle $locked
- added setSetting to set an individual setting by key
- added setSettings to overwrite the entire settings value
- added setIndexes and getIndexes to set/get $indexes

Did Not:
- Did not create a setter for $id because it is made up of entity_type and name
- Did not create a setting for $entity_type because it is set in the constructor
- Did not do anything with $deleted because the documentation mention it is set by a delete() function but I don't see where that function is?
- Did not change all references to $this->name to use $this->getName() or $this->type to $this->getType. Since there is no additional processing happening this seems redundant to me.

yched’s picture

- setName(), setType() : those informations are required in the constructor. Do we really want to add setters for those ?
- setModule() : this is derived from the field type, so not sure there should be a setter either ?

carsonevans’s picture

Working with Bart @ DrupalCon Austin Sprint. We talked through yched's comments and agree so I've updated the patch to reflect them.

I removed:

- setName()
- setType()
- setModule()

markie’s picture

Status: Needs review » Reviewed & tested by the community

I have installed this patch successfully.

carsonevans’s picture

Status: Reviewed & tested by the community » Needs work

Talking at the drupalcon sprint with WebChick and found a few issues that need to be addressed. I am going to go back and re-roll the patch from #12 and then implement yched's comments into that. Also need to add some documentation to a few things.

carsonevans’s picture

FileSize
11.38 KB

This is just a re-roll of czigor's patch from comment #12.

I still need to apply yched's comments but wanted to get the re-roll submitted before tackling that. I'll continue to work on that if this passes the tests.

carsonevans’s picture

Status: Needs work » Needs review

Forgot to mark as needs review to queue the test.

carsonevans’s picture

FileSize
10.63 KB
1.3 KB

Remove setName(), setType(), and setModule()

Status: Needs review » Needs work

The last submitted patch, 32: 2030633-rerolled_with_ycheds_comments_applied-32.patch, failed testing.

carsonevans’s picture

FileSize
732 bytes
10.59 KB

Had a reference to the deleted setModule(). I fixed that.

carsonevans’s picture

Status: Needs work » Needs review
HaloFX’s picture

Status: Needs review » Reviewed & tested by the community

Applied patch from #34. Applied without error, nothing blew up.
Enabled, disabled, and re enabled all field related modules.

HaloFX’s picture

Status: Reviewed & tested by the community » Needs review

Kicking back to needs review for a more in depth look.

Geijutsuka’s picture

Added type hinting where necessary and added comment to locked flag. Big thanks to YesCT for throwing this our way (my first patch!).
Shoutout to:
@AndyThornton
@jackbravo

carsonevans’s picture

This patch intentionally goes against the current standard of making properties public for testing purposes.

This patch will get tested by the testing system and test the assumptions about getters and setters in the rest of the code are correct and to identify any places in core that might need to be updated to use the new getters/setters.

I will submit a corrective patch right after it gets tested.

Status: Needs review » Needs work
carsonevans’s picture

I need some advice on next steps here. There are definitely places where FieldConfig properties are referenced. The failed test points to line 1351 of ContentEntityDatabaseStorage which references deleted instead of using isDeleted(). But the test stops there after it has failed. Three questions I have...

A) For this patch (#38) to be accepted do all the places that reference it as a public property also need to be updated?

B) If so, I have not used SimpleTest before but I assume there is a way for me to get all failures not just the first failure? Otherwise uploading a patch to fix one issue just to wait for test bot is going to be painful. I guess I need to learn simpletest and SimplyTest.me to move this forward.

C) Also, the method in ContentEntityDatabaseStorage type hints a FieldConfigInterface object for the $field it works with. FieldConfigInterface is fairly sparse, only defining isLocked and getBundles. Should we augment it to have a isDeleted(), and potentially other functions, as well?

yched’s picture

Yeah, I'd tend to think this patch doesn't have to convert all direct accesses to the public properties

carsonevans’s picture

Status: Needs work » Needs review
FileSize
10.63 KB

I have uploaded patch from 38 renamed to match this comment number as it was the last passing (and should still pass) patch.

I am not uploading an interdiff because it is the negation of the last interdiff, if that makes sense. If that's incorrect procedure let me know.

I am setting this to needs review to kick off test bot and move it along.

If we want to create a separate issue to change the direct-access to use setters who would do that? I'd like to take a stab at it if that's ok?

yched’s picture

@carsonevans

If we want to create a separate issue to change the direct-access to use setters who would do that? I'd like to take a stab at it if that's ok?

Sure, go for it :-) You can create the issue yourself (tag it with "Novice, Entity Field API"), and link to it in a comment here ?

carsonevans’s picture

carsonevans’s picture

FileSize
10.63 KB

The patch needed to be re-rolled because of format_string was changed to String::format on lines 301, 311, 317, 467

I re-rolled it but couldn't figure out how to do an interdiff that just had the changes that were conflicting.

carsonevans’s picture

YesCT’s picture

Issue summary: View changes

I read through all the lines in this patch. It looks ok to me.
I have not looked at the class to see if any properties are missing getters and setters.

carsonevans’s picture

Here is a table with class properties and associated methods and notes about each to help reviewers. The elements in bold are the ones that have been added in this series of patches.

EDIT: Deleted Table. Reproduced in #51 below with more recent data.

Berdir’s picture

There is no need for setTargetEntityTypeId() because that is also set in the constructor and can not be changed.

Instead of setLocked(), it would also be possible to have lock() and unlock(), not sure what's more clear.

Not sure about getIndexes().. if you look at the documentation, it's never accessed directly from the outside but always only merged into what is returned by getSchema(). I suggest you removed getIndexes() as it could be misleading (does it only return custom indexes or also those defined by the field type?)

New methods should be documented on the interface (FieldConfigInterface) and the implementation should only refer to it with {@inheritdoc}

carsonevans’s picture

All new methods have now been added to the FieldConfigInterface. setTranslatable() was also added to FieldConfigInterface even though it was not introduced in this patch.

Here is a table with class properties and associated methods and notes about each to help reviewers. The elements in bold are the ones that have been added in this series of patches. The notes try to compile most of the previous comments into why we have or haven't added certain getters and setters.

Property Visibility Get Method Set Method Notes
$id public id() N/A The getter will eventually need to be changed to getId() per #2246695: replace all core usages of id() with getid().
There is no setter for $id because it is dervied from $name and $entity_type
$name public getName() N/A There is no setter for $name because it is set in the constructor. See #26.
$entity_type public getTargetEntityTypeId() N/A There is no setter because it is set in the constructor. See #50.
$type public getType() N/A There is no setter for $name because it is set in the constructor. See #26.
$module public getModule() N/A $module is derived from the field type. See #26.
$settings public getSetings()
getSetting()
setSettings()
setSetting()
setSettings will overwrite the entire $settings property. setSetting will set a key within the settings array. This functionality mimics the existing getSettings and getSetting methods.
$cardinality public getCardinality() setCardinality()
$translatable public isTranslatable() setTranslatable() Not added in this patch. setTranslatable was added to FieldConfigInterface.
$locked public isLocked() setLocked()
$indexes public N/A setIndexes() There is no setter because it is set as part of the schema. See #50.
$deleted public isDeleted() setDeleted()
$schema protected getSchema() N/A Not added in this patch.

Status: Needs review » Needs work
carsonevans’s picture

Whoops. Left a getIndexes() in after removing it per #50.

Interdiff-51-53.txt will show the specific error fixed in this latest patch.

Interdiff 46-53.txt is the full meat of the interface and documentation updates that incorporate bedir's comments.

carsonevans’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work
carsonevans’s picture

carsonevans’s picture

LanguageFallbackTest.php failed the first time through. I scanned it but didn't see how it affected FieldConfig so I just re-queued the test. Second time through it passed. I'm not sure if that should be worrisome or not.

Berdir’s picture

Status: Needs work » Reviewed & tested by the community

Looks good to me. Remember to set the issue back to needs review.

Status: Reviewed & tested by the community » Needs work
amitgoyal’s picture

Status: Needs work » Needs review
FileSize
11.26 KB

Patch in #53 no longer applies. Please review updated patch which applies cleanly.

Interdiff failed to create interdiff.txt file so I am not attaching it.

Berdir’s picture

FieldConfig is now FieldStorageConfig.

Status: Needs review » Needs work
undertext’s picture

Status: Needs work » Needs review
FileSize
10.71 KB
m1r1k’s picture

Issue tags: +#ams2014contest

Status: Needs review » Needs work
penyaskito’s picture

Title: Expand FieldConfig with methods » Expand FieldStorageConfig with methods
Issue tags: -

Retitling.

Jānis Bebrītis’s picture

Assigned: carsonevans » Jānis Bebrītis
Status: Needs work » Needs review
FileSize
10.2 KB

Re-rolling #64 for FieldStorageConfig and latest checkout.

daffie’s picture

Status: Needs review » Needs work
Issue tags: +Needs reroll

The entity variables are not protected. They must be. The idea of encapsulation is that you cannot access the variables directly. You must use the functions getVariableName() and setVariableName(). If the variable is a boolean you have the function isVariableName().

The patch is almost a month old so also a reroll.

yched’s picture

The entity variables are not protected. They must be.

Is it what was done in the other issues in #2016679: Expand Entity Type interfaces to provide methods, protect the properties ? Most properties of ConfigEntities are still public, aren't they ?

daffie’s picture

@yched: As far as I know is that the variables must be protected. The whole idea for doing is so is that we have encapsulation of the entity variables. Please correct me if I am wrong.

This is what alexpott said in #2030645: Expand Menu with methods comment #31:

Reclassifying as a bug since exposure of properties as public allows code to not use the API eg ->id vs ->id(). This makes Drupal more stable and prevents bugs. Nice work.

yched’s picture

@daffie: OK, right, this is the new direction for #2016679: Expand Entity Type interfaces to provide methods, protect the properties.
Never mind my #71, #70 is correct.

Status: Needs work » Needs review

Status: Needs review » Needs work
daffie’s picture

The most important problem is that the class variables are not protected. The whole idea of adding functions to get and set the class variables is the principle of encapsulation.

A minor issue:

+++ b/core/modules/field/src/FieldStorageConfigInterface.php
@@ -31,4 +31,92 @@ public function getBundles();
+  /**
+   * Sets the field config deleted property.
+   *
+   * @param bool $deleted
+   *   The field config deleted property.
+   *
+   * @return $this
+   */
+  public function setDeleted($deleted);
+

You need to change @return $this to

  * @return \Drupal\field\FieldStorageConfigInterface
  *   The called FieldStorageConfig entity.
Mile23’s picture

Issue tags: -Needs reroll
FileSize
10.1 KB

@return $this is just fine: https://www.drupal.org/coding-standards/docs#types

Here's a re-roll of #69.

Mile23’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 77: 2030633_77.patch, failed testing.

Mile23’s picture

Status: Needs work » Needs review
FileSize
9.64 KB
936 bytes

Let's fix that re-roll... :-)

daffie’s picture

Status: Needs review » Needs work

@Mile23: The class variables are still public. They must be protected.

daffie’s picture

Assigned: Jānis Bebrītis » Unassigned
YesCT’s picture

Issue summary: View changes
Issue tags: +Needs tests

needs tests, and I think one of the methods is missing a doc block.

We should also think about wether we actually need all these methods, so a reviewer (or someone) should see if/where (in tests?) the methods are used.

this will be an api change.
making the properties protected allows us to make sure we replace all the usages of direct access to them.
And else where we decided that public properties were a bug... so I think we should have the properties protected in this issue also (not sure if the meta is up to date will all this policy/process changes). (See the issue summary in the meta)

OH. this had a follow up to replace all the direct accesses...
#2282299: Accessing FieldConfig properties should be done through methods
Which means... we would have to leave the properties public.

What a mess.

Need to see how a recent one of these issues went in.

YesCT’s picture

Category: Task » Bug report
Issue summary: View changes
Issue tags:

moving this to bug similar to #2030645-31: Expand Menu with methods

and closing #2282299: Accessing FieldConfig properties should be done through methods since we will make the properties protected here.

also updating the issue summary.

https://www.drupal.org/core-mentoring/novice-tasks
The whole issue is not novice, but the next step can be:
making the properties protected.
Make a new patch and add an interdiff. Set to needs review to trigger the test bot. (We know there is more to do here than just that, but it's ok to make little steps of progress.)

daffie’s picture

@YesCT: #2030661: Expand Tour with methods landed 4 days ago and #2030613: Expand EntityViewMode (really EntityDisplayModeBase) with methods landed 5 days ago. Alexpott wants this fixed because he thinks that the exposure of properties as public allows code to not use the API eg ->id vs ->id(). "This makes Drupal more stable and prevents bugs." (see comment #72)

And yes we can add tests, but is that really necessary for getters and setters?

YesCT’s picture

Issue summary: View changes
Issue tags: -Needs tests, -Novice +Novice #SprintWeekend2014

Oh right, if they are just getters and setters, then tests might not be needed. (I googled, and the internet is full of opinions on if getters and setters need to be unit tested.) Maybe just keep your eye out for any methods that are more complicated that might need tests, and update issue summaries to point them out.

updating the summary to take adding tests out of the remaining tasks.

Mile23’s picture

I attacked this problem a bit yesterday and it's a huge refactoring task. It's not like FieldStorageConfig is used by *everything.* :-)

There's no way it's a novice task, and it will be heck to review.

Also, it's not a needs-tests issue, because the tests tell you whether you're on the right path or not. Do not add tests at this point; they'll only be confusing.

I'd suggest going through and changing one property to protected, then make all the tests pass. Then change the next property to protected and make all the tests pass, and so forth. There's no way to parcel this out as multiple issues because of the way some code deals with these properties... Patches would overlap in irreconcilable ways. It might be possible for participants to change one or two properties at a time and then post a patch with an interdiff. Then the next person can work on another property or two after the testbot passes the previous patch.

The relevant tests during this refactoring will be the ones related to field module. Then of course run all of them and see if you're really done. :-)

Ideally, someone who thought these properties should be public would be the one to go through and do this. [evil grin]

daffie’s picture

Before we start making the patch. I would like us to agree on a few points:

  1. I would like that we all agree on which getter and setter functions will be created.
  2. There will be not tests added.
  3. Because it is a huge task. Can we make an agreement over who does what. I am afraid that if we take to long between creating the patch and getting it committed, another issue lands that make our patch needing a reroll.

Maybe a stupid question but can this issue be do with one patch file or do we need multiple patch files?

If alexpott is the one who is going to commit this patch, I would also like a confirmation from him about this.

Mile23’s picture

  1. The getters and setters are already created in the current patch. You can see the discussion about it above. (This is comment #89, after all...)
  2. Yup.
  3. If someone wants to take it on, they can say, "Hey, I'm working on this." Or assign themselves to the issue.
YesCT’s picture

Issue summary: View changes

opps. you are totally right, I meant to only make the task to make them protected a novice task.
changing all the usages is not novice.
updating the issue summary.

YesCT’s picture

Issue summary: View changes
daffie’s picture

@Mile23: I know that there are in your patch. What I really would like is that alexpott signs off on that. So that when the patch is ready and RTBC, we do not get in the discussion over which getter and setter function should or should not be in the patch. With the result that that will take some time and then we need to reroll the patch.

fernando_calsa’s picture

FileSize
9.86 KB
491 bytes

This is my first collaboration to an issue, I have changed the $deleted to protected.

YesCT’s picture

Status: Needs work » Needs review

Thank you @fernando_calsa

Setting to needs review to trigger the testbot. (d.o was making @fernando_calsa wait, thinking the new account might be spamming the comments. I gave them the not the spammer role, which should help for the future.)

@daffie I dont think we should have to clear it with a committer right now, Berdir or yched should be fine (or other person from Maintainers.txt for field stuff).
I think we should read the previous comments from Berdir and yched (if there are any) in this issue about the naming of methods.
And we should put the table in #51 in the issue summary.

I can also look more in depth at that and see what I think about the names and methods, but I would have to read all the comments on the issue and think about it... so let's at least do that before we ping a committer (or Berdir or yched).

YesCT’s picture

Issue summary: View changes

Just a start at summarizing what methods should or shouldn't be in this patch, by copying the table from #51 into the summary.

daffie’s picture

Issue summary: View changes

Status: Needs review » Needs work

The last submitted patch, 93: 2030633-92.patch, failed testing.

YesCT’s picture

Issue summary: View changes
Issue tags: -Novice #SprintWeekend2014 +#SprintWeekend2014

updated the summary remaining tasks to indicate the novice part is done (for now).
also added a column to note change to the property visibility that this patch does.

YesCT’s picture

Issue summary: View changes

oops. just a copy paste mistake.

daffie’s picture

In the issue summery we added the table from comment #51. The table is a proposal for which getter and setter functions to add and not to add to the FieldStorageConfig class. Can one of the field system component maintainers or a branch maintainer sign of on this. This is going to be a big patch and a lot work. In some other sub-issues of #2016679: Expand Entity Type interfaces to provide methods, protect the properties we are getting in a discussion when the patch is made and RTBC over which getter and setter functions to include. The problem for this issue is that that will result in a reroll and a lot of extra work. So I really want an agreement over which getter and setter functions will be included.

daffie’s picture

daffie’s picture

Issue summary: View changes

Talked with alexpott on IRC and think that most functions are oke. But he want to remove setDeleted() and setIndexes(). I have updated the issue summary.

Mile23’s picture

Mile23’s picture

Assigned: Unassigned » Mile23
Mile23’s picture

Status: Needs work » Needs review
FileSize
26.84 KB
13.94 KB

This patch makes all properties of FieldStorgeConfig protected except for: entity_type, field_name, settings, and type.

It removes setDeleted() and setIndexes() from previous patches (and rightly so, I'd wager).

It passes the field module's tests, to the lazy extent that I worked on that, but let's see what the testbot says.

Update: aw crap, I named the interdiff with .patch. Sigh.

Status: Needs review » Needs work

The last submitted patch, 105: interdiff_80.patch, failed testing.

The last submitted patch, 105: 2030633_104.patch, failed testing.

daffie queued 105: 2030633_104.patch for re-testing.

The last submitted patch, 105: 2030633_104.patch, failed testing.

Mile23’s picture

Status: Needs work » Needs review
FileSize
40.92 KB
14.36 KB

Found a lot more. This might fail testing, but it shouldn't have fatal errors.

Status: Needs review » Needs work

The last submitted patch, 110: 2030633_108.patch, failed testing.

Mile23’s picture

Status: Needs work » Needs review
FileSize
43.57 KB
2.64 KB

Fixing a few things... More later as time permits.

Did you know that Drupal\field_ui\Tests\ManageFieldsTest takes 15 minutes to run locally?

Status: Needs review » Needs work

The last submitted patch, 112: 2030633_112.patch, failed testing.

Mile23’s picture

Status: Needs work » Needs review
FileSize
1.69 KB
45.26 KB

This should fix all the test failures since #105.

This patch makes all properties of FieldStorgeConfig protected except for: entity_type, field_name, settings, and type.

I'll get those encapuslated later.

Mile23’s picture

FileSize
46.28 KB
1.54 KB

Add $settings to the list of protected properties.

Status: Needs review » Needs work

The last submitted patch, 115: 2030633_115.patch, failed testing.

Mile23’s picture

Status: Needs work » Postponed
YesCT’s picture

Assigned: Mile23 » Unassigned
Status: Postponed » Needs work

Thank you @Mile23 for moving these issues forward. You have done a lot on these issues.

in
#2398901-16: Image module makes fatal assumptions about EntityInterface
@yched suggests 3 ways forward.

I'm in favor of:

b) Keep separate patches, and each patch temporarily adds setSettings() to the other interface.
Minor overlap, perfectly acceptable, will just mean a reroll when the first one gets in.

--

Unassigning so it is clear anyone can try to do that.
@Mile23 if you start to try that, just make a comment here, so we can avoid two people both doing it.

See also #2030637-39: Expand FieldConfig/BaseFieldOverride/FieldConfigBase with methods

Berdir’s picture

Status: Needs work » Needs review
FileSize
49.17 KB
2.9 KB

Ok, here is a patch that fixes image_entity_presave(), without needing anything more than we already have here.

Notes:
- This does not contradict what I said in [#9466051], I switched to interface checks as that gives better IDE integration, but it would work just as well with checking the entity type ID.
- This method works with exactly two entity types/objects/interfaces. field configs and field storage configs. I'm making it a bit more explicit, but not changing any actual logic, it already did exactly this before.
- There is a fair amount of old code that has only been partially ported. For example, loading the field storage is not necessary, we already have getType() on both interfaces for this. And the default settings are also applied automatically, so we can drop that.
- We can just drop the if/else at the end in #2030637: Expand FieldConfig/BaseFieldOverride/FieldConfigBase with methods, once both interfaces have a setSetting() method.
- This is IMHO better than having a common interface, because a generic settings interface would be meaningless. We know that those two entity types have settings and that we can change them. A generic (entity or data definition) interface with setters for settings does not tell you anything about what kind of settings it includes. That's just an object-version of an array. Also note that FieldStorageConfig does implement DataDefinitionInterface, #2396713: Figure out how to encapsulate writable settings supplied by DataDefinitionInterface would us help nothing here.

If you have questions, ping me in IRC, I think that is a better place to discuss this through than the issue queue.

Mile23’s picture

This does not contradict what I said in [#9466051], I switched to interface checks as that gives better IDE integration, but it would work just as well with checking the entity type ID.

Disagree, but thanks. :-)

I can live with the approach of #119, assuming tests pass.

Still to go on this issue: Encapsulating $entity_type, $field_name, and $type.

Status: Needs review » Needs work

The last submitted patch, 119: 2030633_119.patch, failed testing.

hussainweb’s picture

Status: Needs work » Needs review
FileSize
12.67 KB
61.03 KB

Fixing failures.

Status: Needs review » Needs work

The last submitted patch, 122: 2030633-122.patch, failed testing.

hussainweb’s picture

Status: Needs work » Needs review
FileSize
646 bytes
61.08 KB

That line of code would have worked in PHP 5.5. That is why the IDE didn't report it. Fixing it for PHP 5.4.

Status: Needs review » Needs work

The last submitted patch, 124: 2030633-124.patch, failed testing.

hussainweb’s picture

Status: Needs work » Needs review
FileSize
4.15 KB
63.8 KB

Fixing more failures.

Status: Needs review » Needs work

The last submitted patch, 126: 2030633-126.patch, failed testing.

hussainweb’s picture

Status: Needs work » Needs review
FileSize
4.14 KB
67.46 KB

Fixing more failures. The exception is fixed. Let's see if we find any more places accessing the property directly.

Status: Needs review » Needs work

The last submitted patch, 128: 2030633-128.patch, failed testing.

hussainweb’s picture

Status: Needs work » Needs review
FileSize
1.28 KB
67.94 KB

Fixing the typo and another use of settings property. I think that some of the failures might be random. Let's see if they come up again.

Status: Needs review » Needs work

The last submitted patch, 130: 2030633-130.patch, failed testing.

hussainweb’s picture

Status: Needs work » Needs review
FileSize
950 bytes
68.15 KB

Fixing the problem before moving on. I am sorry for so many interdiffs and patches. :)

hussainweb’s picture

FileSize
14.58 KB
77.37 KB

Moving on with $type property. I am beginning to think it would be better with these as separate issues. The interdiff alone is 15 KB and I am replacing only those that I found with a simple regex. I am sure tests will tell us more.

Status: Needs review » Needs work

The last submitted patch, 133: 2030633-133.patch, failed testing.

hussainweb’s picture

Status: Needs work » Needs review
FileSize
552 bytes
77.63 KB

It seems there was only one cause for all the errors. Let's see.

hussainweb’s picture

FileSize
4.49 KB
81.47 KB

Moving on to $entity_type property. I am replacing it with getEntityTypeId() method wherever I found it. On to the testbot.

Status: Needs review » Needs work

The last submitted patch, 136: 2030633-136.patch, failed testing.

Berdir’s picture

You need to use getTargetEntityTypeId(), get EntityTypeId() is the entity type of your own entity (field_storage_config)

hussainweb’s picture

@Berdir: I actually meant getTargetEntityTypeId() in my previous comment (#136). But it looks like I have used getEntityTypeId() in some places. Fixing that now.

hussainweb’s picture

Status: Needs work » Needs review
FileSize
2.23 KB
81.48 KB

Fixing the method calls as per #138.

hussainweb’s picture

FileSize
5.43 KB
85.04 KB

The last property now: $field_name. I am replacing it with getName() method wherever I found it. May the testbots smile upon it!

hussainweb’s picture

It's been 5 hours and it still shows "Test request sent". I know this is not normal but does this mean that we should initiate a retest somehow?

Status: Needs review » Needs work

The last submitted patch, 141: 2030633-141.patch, failed testing.

The last submitted patch, 141: 2030633-141.patch, failed testing.

hussainweb’s picture

Status: Needs work » Needs review
FileSize
601 bytes
85.14 KB

Fixing the failure.

hussainweb’s picture

Yay! All properties are now protected and all tests are passing. I don't think there is anything else left to do except review.

daffie’s picture

Title: Expand FieldStorageConfig with methods » Expand FieldStorageConfig/FieldConfig/BaseFieldOverride with methods
Status: Needs review » Needs work
Issue tags: -#SprintWeekend2014

Good work hussainweb!

+++ b/core/modules/field/src/Entity/FieldStorageConfig.php
@@ -288,30 +288,36 @@ protected function preSaveNew(EntityStorageInterface $storage) {
+    // Make sure all settings are present, so that a complete field
+    // definition is passed to the various hooks and written to config.
+    $this->settings += $field_type_manager->getDefaultStorageSettings($this->getType());
+
...
+    // @todo Or this? (taken from patch at https://www.drupal.org/node/2030633#comment-9015925)
+    // $entity_manager->getStorage($this->getTargetEntityTypeId())->onFieldStorageDefinitionCreate($this);

@@ -353,6 +359,8 @@ protected function preSaveUpdated(EntityStorageInterface $storage) {
+    // @todo Or this? (taken from patch at https://www.drupal.org/node/2030633#comment-9015925)
+    // $entity_manager->getStorage($this->getTargetEntityTypeId())->onFieldStorageDefinitionUpdate($this, $this->original);

Why is this code necessary for this issue?

+++ b/core/modules/field/src/Entity/FieldStorageConfig.php
@@ -481,10 +491,11 @@ public function getColumns() {
-    if (empty($this->deleted)) {
+    $deleted = $this->isDeleted();
+    if (empty($deleted)) {

Why not do "if ($this->isDeleted()) {"

+++ b/core/modules/field/src/FieldStorageConfigStorage.php
@@ -135,13 +135,28 @@ public function loadByProperties(array $conditions = array()) {
-          case 'uuid';
+          case 'uuid':
...
+          case 'deleted':
+            $checked_value = $field->isDeleted();
+            break;
+
+          case 'module':
+            $checked_value = $field->getModule();
+            break;
+
+          case 'type':
+            $checked_value = $field->getType();
+            break;
+
+          case 'field_name':
+            $checked_value = $field->getName();
+            break;

Good find!!!

+++ b/core/modules/field/src/Tests/FieldCrudTest.php
@@ -191,9 +191,10 @@ function testDeleteFieldCrossDeletion() {
+    $field_name = $field_storage->getName();
...
-    $this->assertFalse(FieldConfig::loadByName('entity_test', $this->fieldDefinition['bundle'], $field_storage->field_name));
-    $this->assertFalse(FieldConfig::loadByName('entity_test', $field_definition_2['bundle'], $field_storage->field_name));
+    $this->assertFalse(FieldConfig::loadByName('entity_test', $this->fieldDefinition['bundle'], $field_name));
+    $this->assertFalse(FieldConfig::loadByName('entity_test', $field_definition_2['bundle'], $field_name));

@@ -202,10 +203,11 @@ function testDeleteFieldCrossDeletion() {
+    $field_name = $field_storage->getName();
...
-    $this->assertTrue(FieldStorageConfig::loadByName('entity_test', $field_storage->field_name));
+    $this->assertTrue(FieldStorageConfig::loadByName('entity_test', $field_name));
...
-    $this->assertFalse(FieldStorageConfig::loadByName('entity_test', $field_storage->field_name));
+    $this->assertFalse(FieldStorageConfig::loadByName('entity_test', $field_name));

I think that directly using $field_storage->getName() is better.

+++ b/core/modules/field_ui/src/Form/FieldStorageEditForm.php
@@ -194,7 +194,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
+      $field_storage->set($key,$value);

Nitpick: add a space between $key, and $value.

+++ b/core/modules/image/image.module
@@ -321,49 +322,52 @@ function image_filter_keyword($value, $current_pixels, $new_pixels) {
 function image_entity_presave(EntityInterface $entity) {

This is not solvable. There is problem with the function image_entity_presave(). See comment https://www.drupal.org/node/2398901#comment-9466051. I think the best option is to merge #2030637: Expand FieldConfig/BaseFieldOverride/FieldConfigBase with methods with this issue. Which I did.

Berdir’s picture

This is not solvable

It is solved or at least will only require a minor update in #2030637: Expand FieldConfig/BaseFieldOverride/FieldConfigBase with methods, which we should postpone on this. Merging the patches will probably double the patch size of this issue again.

daffie’s picture

Title: Expand FieldStorageConfig/FieldConfig/BaseFieldOverride with methods » Expand FieldStorageConfig with methods
daffie’s picture

Please use the solution from #2398901: Image module makes fatal assumptions about EntityInterface:

if ($entity_type == 'field_config') {
  use the correct code (property or method) to manipulate the settings
}
else {
  use the correct code (property or method) to manipulate the settings
}

In #2030637: Expand FieldConfig/BaseFieldOverride/FieldConfigBase with methods shall we remove this construction.

Berdir’s picture

The patch is using interfaces for that, which is the same.

daffie’s picture

To explain the change from comment #150 a little bit more. Change in file image.module on line 343 in the function image_entity_presave() to:

if ($entity_type == 'field_storage_config') {
  $fid = $entity->getSetting('default_image')['fid'];
}
else {
  $fid = $entity->settings['default_image']['fid'];
}

In #2030637: Expand FieldConfig/BaseFieldOverride/FieldConfigBase with methods shall we remove this construction. After that can we easily commit the interface from #2398901: Image module makes fatal assumptions about EntityInterface.

Berdir’s picture

Again, image_entity_presave() is already perfectly fine as far as this issue goes, both objects have a getSetting(), only setSetting() is missing on field_config, and that will be trivial to update in #2030637: Expand FieldConfig/BaseFieldOverride/FieldConfigBase with methods. And I still insist that #2398901: Image module makes fatal assumptions about EntityInterface is going in a wrong direction and is a won't fix.

  1. +++ b/core/modules/field/src/ConfigImporterFieldPurger.php
    @@ -140,7 +140,7 @@ public static function getFieldStoragesToPurge(array $extensions, array $deletes
         foreach ($field_storages as $field_storage) {
    -      if (!in_array($field_storage->module, $providers)) {
    +      if (!in_array($field_storage->getModule(), $providers)) {
             $storages_to_delete[$field_storage->id()] = $field_storage;
           }
    

    Confused why this is still module and not provider. Also fun fact: It is "core" for field types defined in Drupal\Core\Field :)

    But that has nothing to do with this issue, *except* that we might want to name the method getProvider() instead. Not sure.

  2. +++ b/core/modules/field/src/Entity/FieldStorageConfig.php
    @@ -288,30 +288,36 @@ protected function preSaveNew(EntityStorageInterface $storage) {
         $this->module = $field_type['provider'];
     
    +    // Make sure all settings are present, so that a complete field
    +    // definition is passed to the various hooks and written to config.
    +    $this->settings += $field_type_manager->getDefaultStorageSettings($this->getType());
    +
         // Notify the entity manager.
         $entity_manager->onFieldStorageDefinitionCreate($this);
    +    // @todo Or this? (taken from patch at https://www.drupal.org/node/2030633#comment-9015925)
    +    // $entity_manager->getStorage($this->getTargetEntityTypeId())->onFieldStorageDefinitionCreate($this);
       }
    

    As @daffie mentioned, this is strange. I would like to see what exactly fails without adding this, can we have a patch without those changes and then see what happens?

  3. +++ b/core/modules/field/src/Entity/FieldStorageConfig.php
    @@ -353,6 +359,8 @@ protected function preSaveUpdated(EntityStorageInterface $storage) {
         $entity_manager->onFieldStorageDefinitionUpdate($this, $this->original);
    +    // @todo Or this? (taken from patch at https://www.drupal.org/node/2030633#comment-9015925)
    +    // $entity_manager->getStorage($this->getTargetEntityTypeId())->onFieldStorageDefinitionUpdate($this, $this->original);
    

    Same here, no need to change anything here, so drop this.

  4. +++ b/core/modules/field/src/Entity/FieldStorageConfig.php
    @@ -481,10 +491,11 @@ public function getColumns() {
    -    if (empty($this->deleted)) {
    +    $deleted = $this->isDeleted();
    +    if (empty($deleted)) {
    

    yes, as mentioned above, if (!$this->isDeleted()) should be enough here.

  5. +++ b/core/modules/field/src/Entity/FieldStorageConfig.php
    @@ -540,6 +565,22 @@ public function getSetting($setting_name) {
    +    $this->settings[$setting_name] = $value;
    ...
    +    $this->set('settings', $settings);
    
    @@ -591,6 +632,14 @@ public function getCardinality() {
    +    $this->set('cardinality', $cardinality);
    
    @@ -626,6 +675,14 @@ public function isLocked() {
    +    $this->set('locked', $locked);
    

    Why are some methods methods using $this->set() and others not?

    This should be unified. I'm not sure if it as a good idea, but #2399965: Config entity get() and set() should invoke getters/setters wants to change set() so that it calls e.g. setModule(), so calling set() would result in a loop and we should probably access the property directly.

  6. +++ b/core/modules/field/src/FieldStorageConfigInterface.php
    @@ -39,4 +39,72 @@ public function isLocked();
    +   * @return bool
    +   *   The deleted property.
    

    I don't think this should talk about a property, just write something like "Returns TRUE if the field was deleted, FALSE otherwise" or so.

  7. +++ b/core/modules/field/src/FieldStorageConfigInterface.php
    @@ -39,4 +39,72 @@ public function isLocked();
    +   * Sets field settings by overwriting the settings array.
    

    "array" is an implementation detail, I'd write something like "Sets field settings (overwrites existing settings)."

  8. +++ b/core/modules/field/src/FieldStorageConfigInterface.php
    @@ -39,4 +39,72 @@ public function isLocked();
    +   * @param string $settings
    +   *   The array of field settings.
    

    string is wrong.

  9. +++ b/core/modules/field/src/FieldStorageConfigInterface.php
    @@ -39,4 +39,72 @@ public function isLocked();
    +  /**
    +   * Returns the name of the module providing the field type.
    +   *
    +   * @return string
    +   *   The name of the module that provides the field type.
    +   */
    +  public function getModule();
    

    As mentioned above, we use almost everywhere "provider" instead of module now, so maybe we should use that for the method name.

  10. +++ b/core/modules/field/src/FieldStorageConfigStorage.php
    @@ -135,13 +135,28 @@ public function loadByProperties(array $conditions = array()) {
    +          case 'uuid':
                 $checked_value = $field->uuid();
                 break;
     
    +          case 'deleted':
    +            $checked_value = $field->isDeleted();
    +            break;
    +
    +          case 'module':
    +            $checked_value = $field->getModule();
    +            break;
    +
    +          case 'type':
    +            $checked_value = $field->getType();
    +            break;
    +
    +          case 'field_name':
    +            $checked_value = $field->getName();
    +            break;
    +
               default:
                 $checked_value = $field->$key;
    -            break;
             }
    

    This could also use $field->get($key), I'm not sure if this list is really complete. Because the default will definitely not work anymore.

  11. +++ b/core/modules/field/src/Tests/FieldStorageCrudTest.php
    @@ -363,7 +363,11 @@ function testUpdateFieldType() {
    -      $field_storage->type = 'integer';
    +      // Set the field storage type to 'integer.' Since $type is protected,
    +      // we have to use reflection.
    +      $ref_field_storage_type = new \ReflectionProperty($field_storage, 'type');
    +      $ref_field_storage_type->setAccessible(TRUE);
    +      $ref_field_storage_type->setValue($field_storage, 'integer');
           $field_storage->save();
    

    No, we do not, set('type', 'integer') works too.

  12. +++ b/core/modules/field/src/Tests/reEnableModuleFieldTest.php
    @@ -39,6 +39,8 @@ protected function setUp() {
    +   *
    +   * @see \field_system_info_alter()
    

    We usually do not prefix functions with a \.

  13. +++ b/core/modules/system/src/Tests/Entity/FieldSqlStorageTest.php
    @@ -411,15 +411,23 @@ function testFieldUpdateIndexesWithData() {
    -    // Add an index.
    -    $field_storage->indexes = array('value' => array(array('value', 255)));
    +    // Add an index. Since $indexes is protected, we have to use reflection.
    +    $ref_field_storage_indexes = new \ReflectionProperty($field_storage, 'indexes');
    +    $ref_field_storage_indexes->setAccessible(TRUE);
    +    $ref_field_storage_indexes->setValue(
    +      $field_storage,
    +      array('value' => array(array('value', 255)))
    +    );
    

    Same, use set() Or add a setter, because this seems like a valid thing that you might want to set?

yched’s picture

re: #153.1 :
$storage->module / $storage->getModule() :

we might want to name the method getProvider() instead. Not sure.

+1. This issue is breaking BC anyway, we might as well move to something meaningful. Could even be getFieldTypeProvider(), for clarity. This is not the provider of the "storage definition".

re: #153.5 :

@@ -626,6 +675,14 @@ public function isLocked() {
    +    $this->set('locked', $locked);

Why are some methods methods using $this->set() and others not?

Noticed the same pattern in #2030607: Expand EntityDisplayBase with methods, was wondering about that too.

Berdir’s picture

@yched: Thanks for the +1 ;) Do you know a reason why we couldn't get the provider from the plugin definition directly instead of persisting it? I understand that was convenient to have earlier, but when it is a method, it shouldn't matter? that's not a change that belongs in this issue of course, just wondering.

Mile23’s picture

Some of these issues use set() and some don't because it's completely unclear when one should or shouldn't use set().

set() has side-effects. Are they necessary? Is it an API or just something that's there for some reason?

yched’s picture

@Berdir #155:

Do you know a reason why we couldn't get the provider from the plugin definition directly instead of persisting it?

Good question.
IIRC, we persisted it in the field definition to be able to know it in case the providing module went missing (disabled, etc)...
I think that comes from CCK, and was kept in the D7 Field API port.

Later in the D7 cycle, "prevent disabling modules that provide field types in use" was added, and in D8 that area moved further with config dependencies and stuff. So it might be that we could stop saving it in the config files now, yes.

Not directly related to the current patch, though, so it's probably best as a followup / separate issue - opened #2407463: Stop storing the provider module in FieldStorageConfig yamls.

As for this issue here : the current uses of $field_storage->getModule() evidenced by the current patch show that it's still handy to have a method to access it from the $field_storage, so the said followup would still keep the method.
Thus, still +1 on giving it a clearer name like getFieldTypeProvider() in this patch here.

hussainweb’s picture

Status: Needs work » Needs review
Issue tags: +Needs issue summary update
FileSize
81.44 KB

Lot of reviews to work on! I am starting with a reroll. It was quite a massive reroll considering that it is just 15 days. There were conflicts to setting translateable on fields, better loading dump files in migrate tests, #2357801: File field default values are not deployable -- use UUIDs for the default file and some smaller ones.

Setting it to needs review to let this run through the testbot. I will set it to needs work once tests run and will then work on the reviews. I am also adding "Needs issue summary update" as it seems that some of the comments above will need it.

Status: Needs review » Needs work

The last submitted patch, 158: 2030633-158.patch, failed testing.

hussainweb’s picture

Status: Needs work » Needs review
FileSize
81.44 KB

I was afraid I'd miss something. Trying again.

Status: Needs review » Needs work

The last submitted patch, 160: 2030633-160.patch, failed testing.

hussainweb’s picture

Status: Needs work » Needs review
FileSize
81.08 KB

Sorry, it was the exact same patch. Gotta focus.

Status: Needs review » Needs work

The last submitted patch, 162: 2030633-162.patch, failed testing.

hussainweb’s picture

Status: Needs work » Needs review
FileSize
1.57 KB
82.65 KB

Fixing the error (and in other places). I am hoping there won't be many like these as it is not long since the last pass.

Status: Needs review » Needs work

The last submitted patch, 164: 2030633-164.patch, failed testing.

hussainweb’s picture

Status: Needs work » Needs review
FileSize
6.73 KB
82.71 KB
hussainweb’s picture

Status: Needs review » Needs work

Looks good. Setting to needs work for review points.

hussainweb’s picture

Status: Needs work » Needs review
FileSize
8.46 KB
82.13 KB

Working on the simpler review points first.

From #147,
1. Moving this to the next patch.
4. Is there a specific reason why calling getName() every time would be better? I know it does not make a big performance difference but on the other hand, it does not make the code harder to read. Do you still think I should change it?

From #153,
1. Do you think I should rename the property as well? If I understand this correctly, I don't think we can rename the properties without affecting the YAML files as well. In that case, the getter/setter name would be different from the property. I don't think it matters considering we are going to #2407463: Stop storing the provider module in FieldStorageConfig yamls.
2. I will try a separate patch for this.
5. I changed everything I could find to set the property directly.
9. Same as 1.
13. Added getter and setter for indexes property.

Setting it to needs review for testing.

Berdir’s picture

Yes, keep ->module, don't rename that. It is fine if they don't have the same name.

hussainweb’s picture

Issue summary: View changes
FileSize
6.86 KB
82.72 KB

Changing getModule() to getFieldTypeProvider() as per #154. I am also updating the IS to update the getter name.

hussainweb’s picture

FileSize
1.3 KB
82.39 KB

I am creating a patch to see what goes wrong after removing the code mentioned in #147.1 and #153.2.

hussainweb’s picture

So, I guess you don't need that line after all.

I think all the tasks are done. Am I missing something? Please review.

daffie’s picture

Status: Needs review » Needs work
  1. +++ b/core/modules/field/src/Entity/FieldStorageConfig.php
    @@ -755,4 +803,19 @@ public function isDeletable() {
    +  /**
    +   * {@inheritdoc}
    +   */
    +  public function getIndexes() {
    +    return $this->indexes;
    +  }
    +
    +  /**
    +   * {@inheritdoc}
    +   */
    +  public function setIndexes($indexes) {
    +    $this->indexes = $indexes;
    +    return $this;
    +  }
    
    +++ b/core/modules/field/src/FieldStorageConfigInterface.php
    @@ -39,4 +39,90 @@ public function isLocked();
    +  /**
    +   * Returns the custom storage indexes for the field data storage.
    +   *
    +   * @return array
    +   *   An array of custom indexes.
    +   */
    +  public function getIndexes();
    +
    +  /**
    +   * Sets the custom storage indexes for the field data storage..
    +   *
    +   * @param array $indexes
    +   *   The array of custom indexes.
    +   *
    +   * @return $this
    +   */
    +  public function setIndexes($indexes);
    

    These two methods are not necessary. The method getIndexes() is not used anywhere and setIndexes() is only used in tests. Also there is in the issue summary a list with methods to be added. These are not on that list.

  2. +++ b/core/modules/field/src/Tests/FieldCrudTest.php
    @@ -191,9 +191,10 @@ function testDeleteFieldCrossDeletion() {
    +    $field_name = $field_storage->getName();
    ...
    -    $this->assertFalse(FieldConfig::loadByName('entity_test', $this->fieldDefinition['bundle'], $field_storage->field_name));
    -    $this->assertFalse(FieldConfig::loadByName('entity_test', $field_definition_2['bundle'], $field_storage->field_name));
    +    $this->assertFalse(FieldConfig::loadByName('entity_test', $this->fieldDefinition['bundle'], $field_name));
    +    $this->assertFalse(FieldConfig::loadByName('entity_test', $field_definition_2['bundle'], $field_name));
    
    @@ -202,10 +203,11 @@ function testDeleteFieldCrossDeletion() {
    +    $field_name = $field_storage->getName();
    ...
    -    $this->assertTrue(FieldStorageConfig::loadByName('entity_test', $field_storage->field_name));
    +    $this->assertTrue(FieldStorageConfig::loadByName('entity_test', $field_name));
    ...
    -    $this->assertFalse(FieldStorageConfig::loadByName('entity_test', $field_storage->field_name));
    +    $this->assertFalse(FieldStorageConfig::loadByName('entity_test', $field_name));
    

    I think that it is better to replace $field_storage->field_name directly with $field_storage->getName().

  3. +++ b/core/modules/image/image.module
    @@ -441,13 +445,13 @@ function image_field_config_update(FieldConfigInterface $field) {
    +  $uuid = $field->getSettings()['default_image']['uuid'];
    

    Nitpick: Can we be consistent and use $field->getSetting('default_image') instead of $field->getSettings()['default_image']

  4. +++ b/core/modules/image/image.module
    @@ -321,49 +322,52 @@ function image_filter_keyword($value, $current_pixels, $new_pixels) {
    -  $field_storage = FALSE;
    -  $entity_type_id = $entity->getEntityTypeId();
    -  if ($entity_type_id == 'field_config') {
    -    $field_storage = $entity->getFieldStorageDefinition();
    -    $default_settings = \Drupal::service('plugin.manager.field.field_type')->getDefaultFieldSettings('image');
    -  }
    -  elseif ($entity_type_id == 'field_storage_config') {
    -    $field_storage = $entity;
    -    $default_settings = \Drupal::service('plugin.manager.field.field_type')->getDefaultStorageSettings('image');
    +
    +  // Get the default image settings, return if not saving an image field storage
    +  // or image field entity.
    +  if (($entity instanceof FieldStorageConfigInterface || $entity instanceof FieldConfigInterface) && $entity->getType() == 'image') {
    +    $default_image = $entity->getSetting('default_image');
    ...
    -  // Exit, if not saving an image field storage or image field entity.
    -  if (!$field_storage || $field_storage->type != 'image') {
    +  else {
    ...
    -  if ($field_storage->isSyncing()) {
    +  if ($entity->isSyncing()) {
    

    You are changing here far to much. Leave the 'field_config' stuff alone. My suggestion is to change as little as possible.

  5. +++ b/core/modules/image/image.module
    @@ -7,6 +7,7 @@
    +use Drupal\field\Entity\FieldConfig;
    
    @@ -321,49 +322,52 @@ function image_filter_keyword($value, $current_pixels, $new_pixels) {
    +  elseif ($entity instanceof FieldConfig) {
    

    Can we change FieldConfig to FieldConfigInterface and remove the line with "use Drupal\field\Entity\FieldConfig".

Berdir’s picture

1. It is an API. It was added because I suggested to do so above. If missing tests is a blocker then I suggest we simply add a few lines to get the indexes again where we are setting them to verify that part works.

4. No, that is not changing too much. As I've tried to explain you 4 times in this issue already, this method is changing exactly as much as we need there, nothing less, nothing more.

5. I disagree. We access a property, not a method, the property is not defined on the interface. As said before, this will go away as soon as FieldConfig also gets a setSetting() method.

yched’s picture

I still intend to review this at some point very soon, sorry for not being able to do it earlier.

For now, just : agreed with @Berdir on all of #174

Mile23’s picture

Assigned: Unassigned » Mile23
Issue tags: +Needs reroll

#171 needs reroll

Mile23’s picture

Assigned: Mile23 » Unassigned
Issue tags: -Needs reroll
FileSize
82.64 KB

#171 introduces FieldStorageConfig::isRequired(), which is marked up as {@inheritdoc}, but I can't find the method it's overloading. I know this because it's pretty much the reason for the only merge conflict in the reroll. All it does is return FALSE. I've left it in for now.

This doesn't address any changes suggested since #171.

Mile23’s picture

Status: Needs work » Needs review
Berdir’s picture

$ git lg -S isRequired
...
* 82fad36 - Issue #2411323 by tadityar: FieldStorageConfig::isRequired should not exist (5 days ago)

=> I don't think this issue introduced it as it existed in HEAD, but it probably started appearing in the context. Remove it.

Status: Needs review » Needs work

The last submitted patch, 177: 2030633-177.patch, failed testing.

Mile23’s picture

Status: Needs work » Needs review
FileSize
83.32 KB
4.49 KB

Thanks @daffie for the review.

#173.2: Much better to explicitly call getName(). Also, I changed the generic, reused $field_storage to a number of descriptive names which make the test easier to read.

#173.3: If you check the comment right above that line, it says this: // The value of a managed_file element can be an array if #extended == TRUE. I'm not sure whether that's actually true, but the image module's tests pass, so I'm making the change and taking out the comment. (Oops... made a patch with the comment in. Will change that on the next go-round.)

#173.1,4, and 5: Not changing those as per @Berdir in #174.

Also removed isRequired() as per #179.

The last patch failed the migration test, so let's see if that happens again.

Status: Needs review » Needs work

The last submitted patch, 181: 2030633_181.patch, failed testing.

Mile23’s picture

I can't make migrate module pass tests locally against HEAD, so I'll just wait a day or something.

Mile23’s picture

Status: Needs work » Needs review

OK, retesting.

Mile23 queued 181: 2030633_181.patch for re-testing.

Status: Needs review » Needs work

The last submitted patch, 181: 2030633_181.patch, failed testing.

Mile23’s picture

The failing test is MigrateDrupal6Test, which I still can't get to pass locally against HEAD.

Mile23 queued 181: 2030633_181.patch for re-testing.

The last submitted patch, 181: 2030633_181.patch, failed testing.

Mile23’s picture

Status: Needs work » Needs review
FileSize
85.12 KB

Reroll.

Status: Needs review » Needs work

The last submitted patch, 190: 2030633_190.patch, failed testing.

Mile23’s picture

Status: Needs work » Needs review
FileSize
85.83 KB
85.83 KB
724 bytes

Missed one.

Update: Ugh. Looks like I uploaded twice.

daffie’s picture

Status: Needs review » Reviewed & tested by the community

It all looks good to me.
All the methods from the issue summary are added.
Methods getIndexes() and setIndexes() are also added on request of @Berdir (see comment #174). I do not think that is necessary to add those two methods. The first method is never used and the second only in tests. But @Berdir is on the drupal 8 maintainers list, so I am following his lead.
All documentation is in order.
It get a RTBC from me.

yched’s picture

Assigned: Unassigned » yched
Status: Reviewed & tested by the community » Needs review

Thanks a ton for sticking with this, folks.

Been kept in other issues, but I'd really like to have a last look at this before it gets in. Will try hard to do that tomorrow night.

daffie’s picture

Status: Needs review » Needs work
+++ b/core/modules/image/image.module
@@ -321,49 +322,52 @@ function image_filter_keyword($value, $current_pixels, $new_pixels) {
+  // @todo Simplify this in https://www.drupal.org/node/2030637, when both
+  //   interfaces have a setSetting() method.

Can we change the to do issue to #2398901: Image module makes fatal assumptions about EntityInterface. The current to do issue #2030637: Expand FieldConfig/BaseFieldOverride/FieldConfigBase with methods does not fix the problem.

Berdir’s picture

No, we can not. Either this or the other issue needs to get in first, and then the other one needs to be updated.

#2398901: Image module makes fatal assumptions about EntityInterface is still a won't fix in my book.

yched’s picture

Mile23’s picture

#2398901: Image module makes fatal assumptions about EntityInterface is, as noted, a Bug From The Future, and since it's not the future yet, it stands to reason that we won't address it in the present. Let's just get through what we can get through now.

Any review appreciated.

yched’s picture

Thanks for the great work folks ! (and thanks for bearing with my slow reviewing :-/)

This is mostly ready IMO, just a few nitpicks below:

  1. +++ b/core/modules/field/src/Tests/FieldCrudTest.php
    @@ -203,35 +203,35 @@ function testDeleteFieldCrossDeletion() {
    -    $field_storage = $this->fieldStorage;
    +    $delete_this_field_storage = $this->fieldStorage;
    ...
    -    $field_storage = entity_create('field_storage_config', $this->fieldStorageDefinition);
    ...
    +    $delete_last_field_storage = entity_create('field_storage_config', $this->fieldStorageDefinition);
    ...
    -    $field_storage = entity_create('field_storage_config', $this->fieldStorageDefinition);
    ...
    +    $delete_all_field_storage = entity_create('field_storage_config', $this->fieldStorageDefinition);
    

    Not related, and I'm not a fan of the var renames :-)
    Reusing the same simple var name through the course of a test is frequent - can we set them back to $field_storage ?

  2. +++ b/core/modules/field/src/FieldStorageConfigInterface.php
    @@ -16,6 +16,14 @@
     interface FieldStorageConfigInterface extends ConfigEntityInterface, FieldStorageDefinitionInterface {
    

    We should polish the method order so that related methods are next to each other.
    (and same in the implementation class)

    Proposed order :

      public function getType();
      public function getFieldTypeProvider();
      public function getBundles();
      public function isDeletable();
      public function isDeleted();
      public function isLocked();
      public function setLocked($locked);
      public function setCardinality($cardinality);
      public function setSetting($setting_name, $value);
      public function setSettings($settings);
      public function setTranslatable($translatable);
      public function getIndexes();
      public function setIndexes($indexes);
    

    Which also shows that getFieldTypeProvider() should actually be getTypeProvider() (sorry, IIRC I'm the one who suggested that name :-/). We don't use the "Field" prefix anywhere else in that interface.

  3. +++ b/core/modules/field/src/FieldStorageConfigStorage.php
    @@ -135,13 +136,28 @@ public function loadByProperties(array $conditions = array()) {
    +          case 'deleted':
    +            $checked_value = $field->isDeleted();
    +            break;
    +
    +          case 'module':
    +            $checked_value = $field->getFieldTypeProvider();
    +            break;
    +
    +          case 'type':
    +            $checked_value = $field->getType();
                 break;
    +
    +          case 'field_name':
    +            $checked_value = $field->getName();
    +            break;
    +
    +          default:
    +            $checked_value = $field->get($key);
    

    I get it for 'module', but why can't 'deleted', 'type', 'field_name' go through the default case ?

  4. +++ b/core/modules/image/image.module
    @@ -321,49 +322,52 @@ function image_filter_keyword($value, $current_pixels, $new_pixels) {
     function image_entity_presave(EntityInterface $entity) {
    ...
    +
    

    Extra empty line at the beginning of the function

  5. +++ b/core/modules/image/image.module
    @@ -321,49 +322,52 @@ function image_filter_keyword($value, $current_pixels, $new_pixels) {
    -  $field_storage = FALSE;
    -  $entity_type_id = $entity->getEntityTypeId();
    -  if ($entity_type_id == 'field_config') {
    -    $field_storage = $entity->getFieldStorageDefinition();
    -    $default_settings = \Drupal::service('plugin.manager.field.field_type')->getDefaultFieldSettings('image');
    -  }
    -  elseif ($entity_type_id == 'field_storage_config') {
    -    $field_storage = $entity;
    -    $default_settings = \Drupal::service('plugin.manager.field.field_type')->getDefaultStorageSettings('image');
    +
    +  // Get the default image settings, return if not saving an image field storage
    +  // or image field entity.
    +  if (($entity instanceof FieldStorageConfigInterface || $entity instanceof FieldConfigInterface) && $entity->getType() == 'image') {
    +    $default_image = $entity->getSetting('default_image');
       }
    -  // Exit, if not saving an image field storage or image field entity.
    -  if (!$field_storage || $field_storage->type != 'image') {
    +  else {
    

    *Please* let's not rehash the discussion in #2398901: Image module makes fatal assumptions about EntityInterface :-)
    Doing stuff based on $entity->getEntityTypeId() in hook_entity_Xxx() is what Core does. Let's not change it here.

  6. +++ b/core/modules/field/src/FieldStorageConfigInterface.php
    @@ -39,4 +47,90 @@ public function isLocked();
    +  public function setSettings($settings);
    

    should type hint as array

  7. +++ b/core/modules/field/src/FieldStorageConfigInterface.php
    @@ -39,4 +47,90 @@ public function isLocked();
    +  public function setIndexes($indexes);
    

    Same here

Berdir’s picture

5. Ha, I changed it to use interfaces :)

IMHO, it doesn't matter which method you use to identify the entity type. Implementing a type specific hook actually uses *both* methods at the same time, so it can be argued that either is fine :) Using the interface means that you get the right type hints and visual confirmation that those methods really exist and without that, going through the effort to add methods and use them is only half as much fun. The difference to #2398901: Image module makes fatal assumptions about EntityInterface is that we use existing, real interfaces that have a meaning.

If you look at existing implementations in core, you'll notice that interface-based checks are actually quite common, although they are usually limited to checking if it is a config or content entity type. Specific entity type checks in the generic hooks are pretty rare, because then you usually use the type specific one. But as mentioned, all of those actually include a type specific interface check too ;)

yched’s picture

Oh, I see. Yeah, this works for me. Sorry for the noise, forget #199.5

Mile23’s picture

Thanks for the review. I'll poke at it later this evening.

#199.3: I get it for 'module', but why can't 'deleted', 'type', 'field_name' go through the default case ?

Because those properties are now encapsulated and protected, which is the whole point of this issue. :-) There might be a better way to map properties to getters... Suggestions welcome. We *could* just grab them using reflection or something, but part of encapsulation is that there might be side-effects to the getter.

Mile23’s picture

Status: Needs work » Needs review
FileSize
85.5 KB
12.28 KB

Oooookay.

Addressing everything in #199, except .3 and .5.

For .2 I realize now I only changed the order in the interface and not the class, but I'll wait for green from this patch before I fix it.

Status: Needs review » Needs work

The last submitted patch, 203: 2030633_203.patch, failed testing.

Mile23’s picture

:-(

Test run duration: 15 min 43 sec].
[23:15:53] Command [/usr/bin/php ./core/scripts/run-tests.sh --php /usr/bin/php --url http://ip-172-30-0-64/checkout --all --list 2>&1] succeeded.
[23:15:53] Review complete. test_id=972418 result code=8 details=Array
(
    [@reason] => tests were executed, but no results were found
)

Mile23 queued 203: 2030633_203.patch for re-testing.

Mile23’s picture

Status: Needs work » Needs review
yched’s picture

#199.3

[yched] I get it for 'module', but why can't 'deleted', 'type', 'field_name' go through the default case ?
[Mile23] Because those properties are now encapsulated and protected, which is the whole point of this issue. :-)

Sure, but the default case does $field->get($key), so this is not a question of public/protected properties :-)
Actually, even 'module' could go through the default case - when I wrote the above I was mid-review and somehow thought we had renamed the internal 'module' property, but that was wrong.
So, most those cases could just go through the default ?

Mile23’s picture

FileSize
85.18 KB
1.27 KB

Sure, but the default case does $field->get($key), so this is not a question of public/protected properties :-)

I tried it before and it blew up. Tried it just now and it didn't. Let's see what the testbot thinks.

daffie’s picture

Issue summary: View changes
Status: Needs review » Reviewed & tested by the community

It all looks good to me.
All the methods from the issue summary are added.
Methods getIndexes() and setIndexes() are also added on request of @Berdir (see comment #174). I do not think that is necessary to add those two methods. The first method is never used and the second only in tests. But @Berdir is on the drupal 8 maintainers list, so I am following his lead.
All points from @yched from #199 are addressed.
All documentation is in order.
It get a RTBC from me.

yched’s picture

yup, RTBC +1

Thanks a lot folks, see you in #2030637: Expand FieldConfig/BaseFieldOverride/FieldConfigBase with methods - will likely need a reroll when this one gets in ?

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

I'm not a huge fan of adding unused and untested methods (setLocked(), setSettings(), getIndexes()) and API methods that are only used in tests (setCardinality(), setTranslatable() and setIndexes()). But @Berdir and @yched have okay this and I'm not going to block the patch on that.

Committed eebf624 and pushed to 8.0.x. Thanks!

Beta evaluation is in the meta issue.

  • alexpott committed eebf624 on 8.0.x
    Issue #2030633 by hussainweb, Mile23, carsonevans, czigor, Berdir,...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.