Problem/Motivation

Quoting #2016679: Expand Entity Type interfaces to provide methods, protect the properties:

Public properties on our entities allow APIs to be circumvented, and increases the likelihood of introducing bugs because an entity object may not be in a reliable or accurate state. (Additionally, ->something->value is cumbersome DX.)

The result of that issue was:
1) Content entities now have getters and setters which act as wrappers around the get() and set() methods.
2) Config entities now have getters and setters, and don't care about get() and set() at all.

This means that unlike content entities, config entities now have two ways (and code paths) to get or modify a property.
This makes all benefits of the getters and setters moot, since they can be bypassed (and actually are, by CMI, forms, entity_create(), etc).

EDIT: There's also a third way, the constructor, being fixed in #2399999: ConfigEntityBase::__construct() should use set() to populate the values.

For getters, the main benefit is ensuring BC:
- A config entity has first_name and last_name properties, which get deprecated (removed from the forms, kept in schema) in favor of a more generic name property.
The getName() accessor can see if first_name and last_name are available, and use them to construct and return the name. But ->get('name') will bypass that.

For setters, the benefit is data consistency:
Imagine a workflow entity type that has an array of states:

protected $states = array();

public function setStates(array $states) {
  $this->states = $states;
  return $this;
}

This ensures getStates() always returns an array, and the data is always valid. But set('states', 'banana') still works. Sure, it will fail on save when the schema is consulted, but other code has plenty of time to crash until then.

Solution

Change ConfigEntityBase's get() and set() to invoke the getters and setters when found.
The property name is camelized, the method's existence is checked (for first_name we search for getFirstName() and setFirstName()), if found it is used.
Otherwise the old behavior is kept (the property is modified directly).

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

bojanz’s picture

I should say that in an ideal world config entities wouldn't have get( ) and set() at all, and forms would mutate values by calling setters, like Symfony Form does, but it's too late for that now.

bojanz’s picture

Status: Active » Needs review
FileSize
2.33 KB

Initial patch. Let's see what blows up (apart from the blocks which I fixed).

bojanz’s picture

Issue summary: View changes

Status: Needs review » Needs work

The last submitted patch, 2: 2399965-2-config-entity-get-set-accessors.patch, failed testing.

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 2: 2399965-2-config-entity-get-set-accessors.patch, failed testing.

Mile23’s picture

Category: Task » Bug report
Issue tags: +DX (Developer Experience)

+1 on addressing this architectural question, in general.

-1 on punting to get() and set(). Just remove them.

This is all being refactored already in existing issues, under #2016679: Expand Entity Type interfaces to provide methods, protect the properties, so making a decision here about whether classes should add their own accessors, or just call parent::set()/get() will make life a lot easier in those other issues.

Also if keeping get/set is the plan, then we'll need to update the docblock for ConfigEntityBase to explain get and set, when and how to use them, what the API is.

alexpott’s picture

Status: Needs work » Needs review
FileSize
6.31 KB

Got the installer to work and some tests to pass - let's see what else breaks.

Status: Needs review » Needs work

The last submitted patch, 8: 2399965.8.patch, failed testing.

alexpott’s picture

Status: Needs work » Needs review
FileSize
1.66 KB
7.36 KB

I expected more fails but the ConfigImportAll test is pretty extensive :)

bojanz’s picture

I fully support the approach in #10.

We've long ago decided to mandate getters and setters for config entities. Avoiding them via get()/set() is a loophole you can drive a truck through, big enough to make any logic in getters and setters useless. So there's a big potential data consistency issue here which can lead to bugs.
However, there's no way we can kill get() / set() for 8.0. So, we do the next best thing, we make them call the getters and setters.
The patch also has a number of fixes where various getters and setters were calling get() / set() themselves, for no good reason.

$excludedGetters is a bit ugly, but it clearly documents that we have several getters that are currently architecturally wrong, and which do weird things.
We might fix some before 8.0, or (more likely) we might fix them all for 8.1.x. It's still good to show clearly that they need future attention.

So, all in all, we've closed the hole, we've improved core consistency, we've left the room for future cleanups. Good enough for me.

tim.plunkett’s picture

+++ b/core/modules/block/src/Entity/Block.php
@@ -256,7 +256,7 @@ public function getContexts() {
-    return $this->getVisibilityConditions()->getConfiguration();
+    return $this->visibility;

Hm, This should have failed. Adding tests for it.

Mile23’s picture

Mile23’s picture

Status: Needs review » Needs work

$excludedGetters is a bit ugly, but it clearly documents that we have several getters that are currently architecturally wrong, and which do weird things.
We might fix some before 8.0, or (more likely) we might fix them all for 8.1.x. It's still good to show clearly that they need future attention.

Great. Where's the @deprecated annotation, or at least the 'This is an anti-pattern and is bad' comment?

tim.plunkett’s picture

Version: 8.0.x-dev » 8.1.x-dev

I think this is fine for 8.1.x, but too late for 8.0.x IMO

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.0-beta1 was released on March 2, 2016, which means new developments and disruptive changes should now be targeted against the 8.2.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.2.x-dev » 8.3.x-dev

Drupal 8.2.0-beta1 was released on August 3, 2016, which means new developments and disruptive changes should now be targeted against the 8.3.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.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.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.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.

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.

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.

dww’s picture

Category: Bug report » Task
Issue tags: -Needs beta evaluation +Needs reroll, +Bug Smash Initiative

This came up as the daily #bugsmash target today. A couple of us read the title and summary and said "sounds like a task, not a bug". I closely read the whole issue and saw that's how @bojanz submitted it. It was moved to a bug in #7 without any real explanation, other than tagging for DX. Although the change will probably help prevent other bugs, this issue isn't itself fixing a bug. 😉 It's proposing we change our APIs to harden them up, which is still a task. Doesn't mean it's not important. And hopefully this random attention will breath new life into this and help get it actually done. Updating the tags to be more accurate (definitely no longer relevant to any beta evaluation, but needs a reroll).

Thanks,
-Derek

karishmaamin’s picture

Re-rolled patch against 9.4.x. Please review

ranjith_kumar_k_u’s picture

Tried to fix the custom command failure.

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.

immaculatexavier’s picture

The patch #30 does not apply

immaculatexavier’s picture

The status is changed to Need Work.

immaculatexavier’s picture

Status: Needs review » Needs work

The status is changed to Need Work.

Rassoni’s picture

Assigned: Unassigned » Rassoni
Rassoni’s picture

Rassoni’s picture

Status: Needs work » Needs review
Rassoni’s picture

Assigned: Rassoni » Unassigned
immaculatexavier’s picture

Fixed the custom commands against #36

immaculatexavier’s picture

Fixed the custom commands against #40

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.

Medha Kumari’s picture

Reroll the patch #40 with 10.1.x .

needs-review-queue-bot’s picture

Status: Needs review » Needs work
FileSize
144 bytes

The Needs Review Queue Bot tested this issue. It either no longer applies to Drupal core, or fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

Apart from a re-roll or rebase, this issue may need more work to address feedback in the issue or MR comments. To progress an issue, incorporate this feedback as part of the process of updating the issue. This helps other contributors to know what is outstanding.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

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.