Support from Acquia helps fund testing for Drupal Acquia logo

Comments

plach’s picture

Status: Active » Needs review
Issue tags: +Quick fix, +API addition
FileSize
3.14 KB

Here is a patch.

plach’s picture

more tags

plach’s picture

Issue tags: -citcon-sprint +sprint

aw

fago’s picture

Generally, +1 on doing so. Here some thoughts about it:

  • I think hook_entity_prepare() isn't a good a name as it's not talking about forms as all. I think the typical use case for it is pre-populating entity field values for the given form, so we should a) mention that and b) call the hook accordingly. So what about hook_entity_prepare_form() - analogously to hook_entity_prepare_view()?
  • We typically invoke entity generic + entity type specific hooks, so let's do that here as well?
  • The docs should clarify that the hook is just once and not per form rebuild.
  • I think we should pass on the form controller also, such that stuff like the form operation is available in the hook.
plach’s picture

I think hook_entity_prepare() isn't a good a name as it's not talking about forms as all.

I completely agree, I picked the current name to avoid API changes as this allows us to use the existing hook_node_preprare() implementations. It was a conservative choice, but I guess we can still do this before code freeze.

We typically invoke entity generic + entity type specific hooks, so let's do that here as well?

We ARE doing it here as well, otherwise tests wouldn't be green ;)

The docs should clarify that the hook is just once and not per form rebuild.

Good point

I think we should pass on the form controller also

Do you mean explicitly? Because it should be available in the form state (see the example in entity.api.php)

plach’s picture

Gábor Hojtsy’s picture

Status: Needs review » Needs work

Looks generally good except a missing healthy does of dependency injection.

+++ b/core/includes/entity.api.phpundefined
@@ -452,6 +452,27 @@ function hook_entity_display_alter(\Drupal\entity\Plugin\Core\Entity\EntityDispl
+ * Act on an entity object about to be shown on an entity form.
+ *

Acts

+++ b/core/includes/entity.api.phpundefined
@@ -452,6 +452,27 @@ function hook_entity_display_alter(\Drupal\entity\Plugin\Core\Entity\EntityDispl
+  if ($form_state['controller']->getOperation() == 'default') {
+    $entity->label->value = 'Altered label';
+    $form_state['mymodule']['label_altered'] = TRUE;
+  }

I think we are moving away from default in favor of "edit", "delete", etc, no?

+++ b/core/lib/Drupal/Core/Entity/EntityFormController.phpundefined
@@ -414,9 +414,19 @@ public function setEntity(EntityInterface $entity) {
+   *
+   * This can be used to fill in a default values. It then invokes

"in default values"

+++ b/core/lib/Drupal/Core/Entity/EntityFormController.phpundefined
@@ -414,9 +414,19 @@ public function setEntity(EntityInterface $entity) {
+  protected function prepareEntity(array &$form_state) {
+    $handler = \Drupal::moduleHandler();

Well, so @YesCT would say if you call \Drupal from a method, you do it wrong, the modulehandler should be injected on controller creation. She has references to show in case needed :)

+++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewFormControllerBase.phpundefined
@@ -66,6 +66,8 @@ protected function prepareEntity() {
+    // Invoke prepare hooks.
+    parent::prepareEntity($form_state);

You don't have this comment elsewhere either, I don't think we need / should have this here.

plach’s picture

Definitely a good dose of DI ;)

plach’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, entity-prepare-2025991-8.patch, failed testing.

fago’s picture

Do you mean explicitly? Because it should be available in the form state (see the example in entity.api.php)

+++ b/core/includes/entity.api.php
@@ -452,6 +452,27 @@ function hook_entity_display_alter(\Drupal\entity\Plugin\Core\Entity\EntityDispl
+function hook_entity_prepare_form(\Drupal\Core\Entity\EntityInterface $entity, array &$form_state) {

I see we can get the controller via $form_state, but yeah - I think the operation is something most implementations should or will have to check here. I'd pass $operation and $langcode as separate parameters to highlight this will run per operation and language, for anything special people still can go for $form_state['controller'].

+++ b/core/modules/node/node.api.php
@@ -592,23 +593,6 @@ function hook_node_access($node, $op, $account, $langcode) {
-function hook_node_prepare(\Drupal\Core\Entity\EntityInterface $node) {

Why is that removed - shouldn't it be updated instead?

plach’s picture

Status: Needs work » Needs review
FileSize
37.32 KB
12.69 KB

[double post]

plach’s picture

This should fix some failures.

I see we can get the controller via $form_state, but yeah - I think the operation is something most implementations should or will have to check here.

I just realized that ET will need to change the translation object all other hook implementations will work on, and this can be done only by making the controller return the one matching the form langauge after it has been updated by ET. Hence I needed to change the signature to pass along the controller isntaead of the entity. Spoke with Gabor and he agrees on this approach.
We don't need language since it will be available on the translation object, does it feel enough or you still think we should pass the operation explicitly?

Why is that removed - shouldn't it be updated instead?

My bad, I thought we documented just the generic one.

fago’s picture

The patch seems to still pass $entity not $controller as first argument?

Howsoever, I think this should work analogously to hook_entity_prepare_view().

So how about going with hook_entity_prepare_form($entity, $form_display, $operation, $form_state) ?

The passed entity can be just $controller->getEntity() - so that should not make a difference compared to passing $controller. However, imho it's better DX to have all the used parameters separately compared to having to get everything out of the controlller?
Regarding language I agree - it's probably the way it will work in d8 everywhere that you just get a language-aware $entity.

Status: Needs review » Needs work

The last submitted patch, entity-prepare-2025991-12.patch, failed testing.

plach’s picture

Status: Needs work » Needs review
FileSize
38.01 KB
9.1 KB

Implemented #14 :)

plach’s picture

Assigned: Unassigned » plach

I'll try to take this home myself.

Status: Needs review » Needs work

The last submitted patch, entity-prepare-2025991-15.patch, failed testing.

plach’s picture

Status: Needs work » Needs review
FileSize
37.5 KB

Rerolled.

Status: Needs review » Needs work

The last submitted patch, entity-prepare-2025991-19.patch, failed testing.

plach’s picture

Status: Needs work » Needs review
FileSize
37.64 KB

This should be green.

plach’s picture

Fixed a couple of things in comments and API docs.

Status: Needs review » Needs work

The last submitted patch, entity-prepare-2025991-22.patch, failed testing.

plach’s picture

Status: Needs work » Needs review
FileSize
37.75 KB
1.6 KB

This time for real :)

Gábor Hojtsy’s picture

Status: Needs review » Reviewed & tested by the community

I found nothing to complain about, not even code style and @plach walked me through the recent changes too.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
git ac https://drupal.org/files/entity-prepare-2025991-23.patch
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 38655  100 38655    0     0  12157      0  0:00:03  0:00:03 --:--:-- 13914
error: patch failed: core/modules/node/lib/Drupal/node/NodeFormController.php:18
error: core/modules/node/lib/Drupal/node/NodeFormController.php: patch does not apply
David Hernández’s picture

Status: Needs work » Reviewed & tested by the community
FileSize
36.37 KB

Re-roll

David Hernández’s picture

Status: Reviewed & tested by the community » Needs review

Changed status

Status: Needs review » Needs work

The last submitted patch, entity-prepare-2025991-26.patch, failed testing.

plach’s picture

Status: Needs work » Needs review
FileSize
37.75 KB

The reroll was missing some pieces, this one should be complete. Let's wait for the bot.

Status: Needs review » Needs work

The last submitted patch, entity-prepare-2025991-27.patch, failed testing.

plach’s picture

Status: Needs work » Needs review
FileSize
39.34 KB
1.59 KB

We have one brand new form controller after #111715: Convert node/content types into configuration :)

Status: Needs review » Needs work

The last submitted patch, entity-prepare-2025991-32.patch, failed testing.

plach’s picture

Status: Needs work » Needs review
FileSize
40.83 KB
1.49 KB

Actually two form controllers, and a random failure :(

Gábor Hojtsy’s picture

Status: Needs review » Reviewed & tested by the community

Looks good, reviewed multiple times above.

tim.plunkett’s picture

+++ b/core/includes/entity.api.phpundefined
@@ -452,6 +452,31 @@ function hook_entity_display_alter(\Drupal\entity\Plugin\Core\Entity\EntityDispl
+function hook_entity_prepare_form(\Drupal\Core\Entity\EntityInterface $entity, $form_display, $operation, array &$form_state) {
+  if ($operation == 'edit') {
+    $entity->label->value = 'Altered label';
+    $form_state['mymodule']['label_altered'] = TRUE;
+  }

What does this do that a form alter cannot? Seems strangely overkill

+++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewEditFormController.phpundefined
@@ -39,12 +40,16 @@ class ViewEditFormController extends ViewFormControllerBase implements EntityCon
-  public function __construct(TempStoreFactory $temp_store_factory, Request $request) {
+  public function __construct(ModuleHandlerInterface $module_handler, TempStoreFactory $temp_store_factory, Request $request) {

This just worsens the DX for a simple entity form.

+++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewFormControllerBase.phpundefined
@@ -41,7 +41,7 @@ public function init(array &$form_state) {
-  protected function prepareEntity() {
+  protected function prepareEntity(array &$form_state) {

I went out of my way to *not* pass $form_state to prepareEntity

+++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewPreviewFormController.phpundefined
@@ -26,18 +27,23 @@ class ViewPreviewFormController extends ViewFormControllerBase implements Entity
+  public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info, $operation = NULL) {

Why is $operation added here?

alexpott’s picture

Status: Reviewed & tested by the community » Needs review

Based on #36 I think we need more discussion here...

plach’s picture

What does this do that a form alter cannot? Seems strangely overkill

For instance it changes the entity values before field widgets are generated. Changing the default values keys afterwards would be much harder. The use case I had in mind was being able to switch the form language before the form is built.

This just worsens the DX for a simple entity form.

Why? If it has no additional constructor parameter it can skip it altogether and things will just work. See NodeTypeFormController for instance.

I went out of my way to *not* pass $form_state to prepareEntity

Why? It's a form hook after all.

Why is $operation added here?

Just a reroll issue I think.

plach’s picture

Spoke with Tim in IRC. This one should be better.

tim.plunkett’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: -Quick fix

This is much more reasonable, IMO.
Back to RTBC if green.

+++ b/core/lib/Drupal/Core/Entity/EntityManager.phpundefined
@@ -227,11 +227,11 @@ public function getFormController($entity_type, $operation) {
+        $this->controllers['form'][$operation][$entity_type] = new $class($this->container->get('module_handler'));
       }
+      $this->controllers['form'][$operation][$entity_type]->setOperation($operation);

Btw, I like this change.

alexpott’s picture

Title: Introduce hook_entity_prepare() to generalize hook_node_prepare() » Change notice: Introduce hook_entity_prepare() to generalize hook_node_prepare()
Priority: Normal » Critical
Status: Reviewed & tested by the community » Active
Issue tags: +Needs change record

Committed f74d298 and pushed to 8.x. Thanks!

Let's ensure the change notices are up-to-date...

https://drupal.org/list-changes/drupal?keywords_description=EntityFormCo...

plach’s picture

Status: Active » Needs review
Issue tags: -Needs change record

Added a paragraph about hook_entity_prepare_form() in the API changes section of https://drupal.org/node/1734556.

plach’s picture

Title: Change notice: Introduce hook_entity_prepare() to generalize hook_node_prepare() » Change notice: Introduce hook_entity_prepare_form() to generalize hook_node_prepare()

Also renaming for easier tracking.

catch’s picture

Issue tags: +Needs change record
penyaskito’s picture

I read the change notice and looks clear to me. The only thing that confused me is the example of hook_menu, because I expected to find a Routing example instead.

plach’s picture

Well, that was already there :)

Gábor Hojtsy’s picture

Title: Change notice: Introduce hook_entity_prepare_form() to generalize hook_node_prepare() » Introduce hook_entity_prepare_form() to generalize hook_node_prepare()
Priority: Critical » Normal
Issue tags: -Needs change record, -sprint

That menu example is adding a local tab. Those are still in flux, so I would not bother with keeping that updated to interim APIs. It was already there before. Thanks for the update!

plach’s picture

Status: Needs review » Fixed

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